From 26b87df36cb8e004d2012d66c1f2ab5a12d3afdf Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 16 Jan 2025 01:56:57 +0530 Subject: [PATCH 1/9] custom error, emit salt --- src/TWCloneFactory.sol | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index eaf86c47..412aaca3 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -5,8 +5,12 @@ import {LibClone} from "@solady/utils/LibClone.sol"; contract TWCloneFactory { + error ProxyDeploymentFailed(); + /// @dev Emitted when a proxy is deployed. - event ProxyDeployed(address indexed implementation, address proxy, address indexed deployer, bytes data); + event ProxyDeployed( + address indexed implementation, address indexed proxy, address indexed deployer, bytes32 inputSalt, bytes data + ); /// @dev Deploys a proxy that points to the given implementation. function deployProxyByImplementation(address implementation, bytes memory data, bytes32 salt) @@ -16,12 +20,15 @@ contract TWCloneFactory { bytes32 saltHash = _guard(salt, data); deployedProxy = LibClone.cloneDeterministic(implementation, saltHash); - emit ProxyDeployed(implementation, deployedProxy, msg.sender, data); + emit ProxyDeployed(implementation, deployedProxy, msg.sender, salt, data); 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(); + } } } From 381dc5fbfe29a4a7e93f78ed0d4e7fcfa0894917 Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 17 Jan 2025 07:08:10 +0530 Subject: [PATCH 2/9] update guard, add older functions --- src/TWCloneFactory.sol | 65 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index 412aaca3..6c5ee827 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -7,20 +7,52 @@ contract TWCloneFactory { error ProxyDeploymentFailed(); + /// Deprecated - required for backward compatibility /// @dev Emitted when a proxy is deployed. - event ProxyDeployed( - address indexed implementation, address indexed proxy, address indexed deployer, bytes32 inputSalt, bytes data + 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 - 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.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 ProxyDeployed(implementation, deployedProxy, msg.sender, salt, data); + emit ProxyDeployedV2(implementation, deployedProxy, msg.sender, salt, data, extraData); if (data.length > 0) { // slither-disable-next-line unused-return @@ -33,20 +65,29 @@ contract TWCloneFactory { } 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; } } From c2e0dc55a2004352eec9d28639530a3835a1b5cb Mon Sep 17 00:00:00 2001 From: Yash <72552910+kumaryash90@users.noreply.github.com> Date: Mon, 3 Feb 2025 23:20:34 +0530 Subject: [PATCH 3/9] Use salt guard in legacy function Signed-off-by: Yash <72552910+kumaryash90@users.noreply.github.com> --- src/TWCloneFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index 6c5ee827..baeb853d 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -27,7 +27,7 @@ contract TWCloneFactory { public returns (address deployedProxy) { - bytes32 saltHash = keccak256(abi.encodePacked(msg.sender, _salt)); + bytes32 saltHash = keccak256(abi.encode(_guard(_salt, _data), msg.sender)); deployedProxy = LibClone.cloneDeterministic(_implementation, saltHash); emit ProxyDeployed(_implementation, deployedProxy, msg.sender); From be54b7875a6bb365047bcab8d651f139e59bed5e Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 10 Feb 2025 21:30:27 +0530 Subject: [PATCH 4/9] change name --- src/TWCloneFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index baeb853d..be2f87fa 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {LibClone} from "@solady/utils/LibClone.sol"; -contract TWCloneFactory { +contract TWCloneFactoryV2 { error ProxyDeploymentFailed(); From feac35b2f9b35f41ec2d4087994bf7592335180d Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 10 Feb 2025 21:50:47 +0530 Subject: [PATCH 5/9] protect salt --- src/TWCloneFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index be2f87fa..58df61ac 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -76,7 +76,7 @@ contract TWCloneFactoryV2 { if (allowCrossChainDeployment && encodeDataIntoSalt) { saltHash = keccak256(abi.encode(salt, data)); } else if (allowCrossChainDeployment && !encodeDataIntoSalt) { - saltHash = salt; + saltHash = keccak256(salt); } else if (!allowCrossChainDeployment && encodeDataIntoSalt) { saltHash = keccak256(abi.encode(salt, block.chainid, data)); } else { From 69d6e63c4eaaca6a27bf2b717509cabb524df317 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 10 Feb 2025 21:59:48 +0530 Subject: [PATCH 6/9] guard not required for legacy function --- src/TWCloneFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index 58df61ac..561d6801 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -27,7 +27,7 @@ contract TWCloneFactoryV2 { public returns (address deployedProxy) { - bytes32 saltHash = keccak256(abi.encode(_guard(_salt, _data), msg.sender)); + bytes32 saltHash = keccak256(abi.encodePacked(msg.sender, _salt)); deployedProxy = LibClone.cloneDeterministic(_implementation, saltHash); emit ProxyDeployed(_implementation, deployedProxy, msg.sender); From b785031de9ab886ed2dbc1037fc0cc4ff1cdc255 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 10 Feb 2025 22:09:23 +0530 Subject: [PATCH 7/9] fix build --- script/superchain/DeployTWCloneFactory.s.sol | 4 ++-- src/TWCloneFactory.sol | 2 +- test/TWCloneFactory.t.sol | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/script/superchain/DeployTWCloneFactory.s.sol b/script/superchain/DeployTWCloneFactory.s.sol index 0d0c4f43..e0dd73e2 100644 --- a/script/superchain/DeployTWCloneFactory.s.sol +++ b/script/superchain/DeployTWCloneFactory.s.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import "lib/forge-std/src/console.sol"; -import {TWCloneFactory} from "src/TWCloneFactory.sol"; +import {TWCloneFactoryV2} from "src/TWCloneFactory.sol"; import {SuperChainInterop} from "src/module/token/crosschain/SuperChainInterop.sol"; interface ICreateX { @@ -33,7 +33,7 @@ contract DeployTWCloneFactoryScript is Script { vm.startBroadcast(testPrivateKey); bytes32 salt; - bytes memory initCode = abi.encodePacked(type(TWCloneFactory).creationCode); + bytes memory initCode = abi.encodePacked(type(TWCloneFactoryV2).creationCode); address twCloneFactory = ICreateX(createX).deployCreate2(salt, initCode); console.log("TWCloneFactory deployed: ", twCloneFactory); diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index 561d6801..1bf0619d 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -76,7 +76,7 @@ contract TWCloneFactoryV2 { if (allowCrossChainDeployment && encodeDataIntoSalt) { saltHash = keccak256(abi.encode(salt, data)); } else if (allowCrossChainDeployment && !encodeDataIntoSalt) { - saltHash = keccak256(salt); + saltHash = keccak256(abi.encode(salt)); } else if (!allowCrossChainDeployment && encodeDataIntoSalt) { saltHash = keccak256(abi.encode(salt, block.chainid, data)); } else { diff --git a/test/TWCloneFactory.t.sol b/test/TWCloneFactory.t.sol index af8c9713..e3cf867b 100644 --- a/test/TWCloneFactory.t.sol +++ b/test/TWCloneFactory.t.sol @@ -17,14 +17,14 @@ contract MockImplementation { contract TWCloneFactoryTest is Test { - TWCloneFactory factory; + TWCloneFactoryV2 factory; MockImplementation implementation; uint256 chainId1 = 1; uint256 chainId2 = 2; function setUp() public { - factory = new TWCloneFactory(); + factory = new TWCloneFactoryV2(); implementation = new MockImplementation(); } From 411ffece5176fc4850272c52a75d1fc2d179ed5b Mon Sep 17 00:00:00 2001 From: Yash Date: Tue, 11 Feb 2025 23:34:10 +0530 Subject: [PATCH 8/9] rename --- script/superchain/DeployTWCloneFactory.s.sol | 4 ++-- src/TWCloneFactory.sol | 2 +- test/TWCloneFactory.t.sol | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/script/superchain/DeployTWCloneFactory.s.sol b/script/superchain/DeployTWCloneFactory.s.sol index e0dd73e2..0d0c4f43 100644 --- a/script/superchain/DeployTWCloneFactory.s.sol +++ b/script/superchain/DeployTWCloneFactory.s.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import "lib/forge-std/src/console.sol"; -import {TWCloneFactoryV2} from "src/TWCloneFactory.sol"; +import {TWCloneFactory} from "src/TWCloneFactory.sol"; import {SuperChainInterop} from "src/module/token/crosschain/SuperChainInterop.sol"; interface ICreateX { @@ -33,7 +33,7 @@ contract DeployTWCloneFactoryScript is Script { vm.startBroadcast(testPrivateKey); bytes32 salt; - bytes memory initCode = abi.encodePacked(type(TWCloneFactoryV2).creationCode); + bytes memory initCode = abi.encodePacked(type(TWCloneFactory).creationCode); address twCloneFactory = ICreateX(createX).deployCreate2(salt, initCode); console.log("TWCloneFactory deployed: ", twCloneFactory); diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index 1bf0619d..de58e2e4 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {LibClone} from "@solady/utils/LibClone.sol"; -contract TWCloneFactoryV2 { +contract TWCloneFactory { error ProxyDeploymentFailed(); diff --git a/test/TWCloneFactory.t.sol b/test/TWCloneFactory.t.sol index e3cf867b..af8c9713 100644 --- a/test/TWCloneFactory.t.sol +++ b/test/TWCloneFactory.t.sol @@ -17,14 +17,14 @@ contract MockImplementation { contract TWCloneFactoryTest is Test { - TWCloneFactoryV2 factory; + TWCloneFactory factory; MockImplementation implementation; uint256 chainId1 = 1; uint256 chainId2 = 2; function setUp() public { - factory = new TWCloneFactoryV2(); + factory = new TWCloneFactory(); implementation = new MockImplementation(); } From 58b64cef288efbb3a8f912b369ea7ac2f70bbd65 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 12 Feb 2025 00:21:15 +0530 Subject: [PATCH 9/9] comments --- src/TWCloneFactory.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TWCloneFactory.sol b/src/TWCloneFactory.sol index de58e2e4..626435ed 100644 --- a/src/TWCloneFactory.sol +++ b/src/TWCloneFactory.sol @@ -7,7 +7,7 @@ contract TWCloneFactory { error ProxyDeploymentFailed(); - /// Deprecated - required for backward compatibility + /// Deprecated /// @dev Emitted when a proxy is deployed. event ProxyDeployed(address indexed implementation, address proxy, address indexed deployer); @@ -21,7 +21,7 @@ contract TWCloneFactory { bytes extraData ); - /// Deprecated - required for backward compatibility + /// Deprecated /// @dev Deploys a proxy that points to the given implementation. function deployProxyByImplementation(address _implementation, bytes memory _data, bytes32 _salt) public