diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index eaf86c47..baeb853d 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -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; } }