TWCloneFactory
0x25548ba29a0071f30e4bdcd98ea72f79341b07a1
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
2,118 bytes
ABI entries
5
0 read · 2 write
License
none
Contract information
- Address
- 0x25548ba29a0071f30e4bdcd98ea72f79341b07a1
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0x4e59b44847…26c0B4956C
- Creation tx
- 0x1ad7534ba5…3642eb0fac
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (0)
No read functions
The ABI is unavailable or exposes no view functions.
Events (2)
ProxyDeployedProxyDeployedV2
ABI
[
{
"inputs": [],
"name": "ProxyDeploymentFailed",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "deployer",
"type": "address"
}
],
"name": "ProxyDeployed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "deployer",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "inputSalt",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "bytes",
"name": "data",
"type": "bytes"
},
{
"indexed": false,
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
}
],
"name": "ProxyDeployedV2",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "_implementation",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "_salt",
"type": "bytes32"
}
],
"name": "deployProxyByImplementation",
"outputs": [
{
"internalType": "address",
"name": "deployedProxy",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "implementation",
"type": "address"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "salt",
"type": "bytes32"
},
{
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
}
],
"name": "deployProxyByImplementationV2",
"outputs": [
{
"internalType": "address",
"name": "deployedProxy",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;
import {LibClone} from "@solady/utils/LibClone.sol";
contract TWCloneFactory {
error ProxyDeploymentFailed();
/// Deprecated
/// @dev Emitted when a proxy is deployed.
event ProxyDeployed(address indexed implementation, address proxy, address indexed deployer);
/// @dev Emitted when a proxy is deployed.
event ProxyDeployedV2(
address indexed implementation,
address indexed proxy,
address indexed deployer,
bytes32 inputSalt,
bytes data,
bytes extraData
);
/// Deprecated
/// @dev Deploys a proxy that points to the given implementation.
function deployProxyByImplementation(address _implementation, bytes memory _data, bytes32 _salt)
public
returns (address deployedProxy)
{
bytes32 saltHash = keccak256(abi.encodePacked(msg.sender, _salt));
deployedProxy = LibClone.cloneDeterministic(_implementation, saltHash);
emit ProxyDeployed(_implementation, deployedProxy, msg.sender);
if (_data.length > 0) {
// slither-disable-next-line unused-return
(bool success,) = deployedProxy.call(_data);
if (!success) {
revert ProxyDeploymentFailed();
}
}
}
/// @dev Deploys a proxy that points to the given implementation.
function deployProxyByImplementationV2(
address implementation,
bytes memory data,
bytes32 salt,
bytes memory extraData
) public returns (address deployedProxy) {
bytes32 saltHash = _guard(salt, data);
deployedProxy = LibClone.cloneDeterministic(implementation, saltHash);
emit ProxyDeployedV2(implementation, deployedProxy, msg.sender, salt, data, extraData);
if (data.length > 0) {
// slither-disable-next-line unused-return
(bool success,) = deployedProxy.call(data);
if (!success) {
revert ProxyDeploymentFailed();
}
}
}
function _guard(bytes32 salt, bytes memory data) internal view returns (bytes32) {
// check bit 0
bool allowCrossChainDeployment = (salt[0] & bytes1(uint8(1))) != bytes1(0);
// check bit 1
bool encodeDataIntoSalt = (salt[0] & bytes1(uint8(2))) != bytes1(0);
// check bit 2
bool useMsgSender = (salt[0] & bytes1(uint8(4))) != bytes1(0);
bytes32 saltHash;
if (allowCrossChainDeployment && encodeDataIntoSalt) {
saltHash = keccak256(abi.encode(salt, data));
} else if (allowCrossChainDeployment && !encodeDataIntoSalt) {
saltHash = keccak256(abi.encode(salt));
} else if (!allowCrossChainDeployment && encodeDataIntoSalt) {
saltHash = keccak256(abi.encode(salt, block.chainid, data));
} else {
saltHash = keccak256(abi.encode(salt, block.chainid));
}
if(useMsgSender) {
keccak256(abi.encode(saltHash, msg.sender));
}
return saltHash;
}
}
Chain explorer6053msChain node105ms