Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revise clone factory #190

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 60 additions & 12 deletions src/TWCloneFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,89 @@ import {LibClone} from "@solady/utils/LibClone.sol";

contract TWCloneFactory {

error ProxyDeploymentFailed();

/// Deprecated - required for backward compatibility
/// @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 ProxyDeployed(address indexed implementation, address proxy, address indexed deployer, bytes data);
event ProxyDeployedV2(
address indexed implementation,
address indexed proxy,
address indexed deployer,
bytes32 inputSalt,
bytes data,
bytes extraData
);

/// Deprecated - required for backward compatibility
/// @dev Deploys a proxy that points to the given implementation.
function deployProxyByImplementation(address implementation, bytes memory data, bytes32 salt)
function deployProxyByImplementation(address _implementation, bytes memory _data, bytes32 _salt)
public
returns (address deployedProxy)
{
bytes32 saltHash = keccak256(abi.encode(_guard(_salt, _data), msg.sender));
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 ProxyDeployed(implementation, deployedProxy, msg.sender, data);
emit ProxyDeployedV2(implementation, deployedProxy, msg.sender, salt, data, extraData);

if (data.length > 0) {
// slither-disable-next-line unused-return
(bool success,) = deployedProxy.call(data);
require(success, "TWCloneFactory: proxy deployment failed");

if (!success) {
revert ProxyDeploymentFailed();
}
}
}

function _guard(bytes32 salt, bytes memory data) internal view returns (bytes32) {
// 01 if cross chain deployment is allowed
// 00 if cross chain deployment is not allowed
bool allowCrossChainDeployment = bytes1(salt[0]) == hex"01";
bool encodeDataIntoSalt = bytes1(salt[1]) == hex"01";
// 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) {
return keccak256(abi.encode(salt, data));
saltHash = keccak256(abi.encode(salt, data));
} else if (allowCrossChainDeployment && !encodeDataIntoSalt) {
return salt;
saltHash = salt;
} else if (!allowCrossChainDeployment && encodeDataIntoSalt) {
return keccak256(abi.encode(salt, block.chainid, data));
saltHash = keccak256(abi.encode(salt, block.chainid, data));
} else {
return keccak256(abi.encode(salt, block.chainid));
saltHash = keccak256(abi.encode(salt, block.chainid));
}

if(useMsgSender) {
keccak256(abi.encode(saltHash, msg.sender));
}

return saltHash;
}

}