├── .gitmodules ├── foundry.toml ├── test └── Contract.t.sol ├── submit_presigned_keyless_create.sh ├── README.md ├── src └── Create2DeployScriptBase.s.sol ├── inefficient_create2_calldata └── efficient_create2_calldata /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [local] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | remappings = [ 6 | 'ds-test/=lib/forge-std/lib/ds-test/src/', 7 | 'forge-std/=lib/forge-std/src/' 8 | ] 9 | 10 | # See more config options https://github.com/foundry-rs/foundry/tree/master/config -------------------------------------------------------------------------------- /test/Contract.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.13; 3 | 4 | import "forge-std/Test.sol"; 5 | 6 | contract ContractTest is Test { 7 | function setUp() public {} 8 | 9 | function testExample() public { 10 | assertTrue(true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /submit_presigned_keyless_create.sh: -------------------------------------------------------------------------------- 1 | curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xf87e8085174876e800830186a08080ad601f80600e600039806000f350fe60003681823780368234f58015156014578182fd5b80825250506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222"],"id":1}' $ETH_RPC_URL > /dev/null -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # foundry-create2-deployer 2 | 3 | **Currently a work in progress** - Currently stuck until Foundry implements multiple forks per test, as the script cannot read code deployed in the same transaction (I think) 4 | 5 | 6 | `src/Create2DeployScriptBase.s.sol` serves as a basis for Foundry scripts meant to deploy contracts to a deterministic address on any network using `CREATE2_DEPLOYER.safeCreate2(salt, code)`, which has the following interface: 7 | 8 | ```solidity 9 | interface ImmutableCreate2Factory { 10 | function safeCreate2(bytes32 salt , bytes memory contractCreationCode) external; 11 | } 12 | ``` 13 | 14 | Where `salt` is a `bytes32` with the `msg.sender`'s address encoded as the first 160 bits, and `contractCreationCode` is the code to be deployed. 15 | 16 | # Usage 17 | 18 | The `setUp()` method of `Create2DeployerBase.s.sol` performs the following checks and steps: 19 | 20 | 1. Check that the `KEYLESS_CREATE2_FACTORY` is deployed to the network 21 | - If not, check that `KEYLESS_CREATE2_DEPLOYER` has sufficient funds to deploy the `KEYLESS_CREATE2_FACTORY` 22 | - If not, send funds (0.01 of the native token) to the `KEYLESS_CREATE2_DEPLOYER` 23 | - Submit a pre-signed transaction from `KEYLESS_CREATE2_DEPLOYER` to deploy the `KEYLESS_CREATE2_FACTORY` 24 | 2. Check that the `INEFFICIENT_IMMUTABLE_CREATE2_FACTORY` is deployed to the network 25 | - If not, submit a transaction to `KEYLESS_CREATE2` to deploy the `INEFFICIENT_IMMUTABLE_CREATE2_FACTORY` 26 | 3. Check that the `EFFICIENT_IMMUTABLE_CREATE2_FACTORY` is deployed to the network 27 | - If not, submit a transaction to `INEFFICIENT_IMMUTABLE_CREATE2_FACTORY` to deploy the `EFFICIENT_IMMUTABLE_CREATE2_FACTORY` 28 | 29 | When overriding the base script, calls to `super.setUp()` will ensure that the `CREATE2_DEPLOYER` is available on the network before the body of the script's `run()` function is executed. -------------------------------------------------------------------------------- /src/Create2DeployScriptBase.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.13; 3 | 4 | import "forge-std/Script.sol"; 5 | import "forge-std/Test.sol"; 6 | 7 | interface ImmutableCreate2Factory { 8 | function safeCreate2(bytes32, bytes memory) external; 9 | } 10 | 11 | contract Create2DeployScriptBase is Script, Test { 12 | address private constant KEYLESS_CREATE2_DEPLOYER = 13 | 0x4c8D290a1B368ac4728d83a9e8321fC3af2b39b1; 14 | address private constant KEYLESS_CREATE2_FACTORY = 15 | 0x7A0D94F55792C434d74a40883C6ed8545E406D12; 16 | address private constant INEFFICIENT_IMMUTABLE_CREATE2_FACTORY = 17 | 0xcfA3A7637547094fF06246817a35B8333C315196; 18 | address private constant EFFICIENT_IMMUTABLE_CREATE2_FACTORY = 19 | 0x0000000000FFe8B47B3e2130213B802212439497; 20 | ImmutableCreate2Factory constant CREATE2_DEPLOYER = 21 | ImmutableCreate2Factory(EFFICIENT_IMMUTABLE_CREATE2_FACTORY); 22 | 23 | function setUp() public { 24 | vm.broadcast(); 25 | _checkOrDeployKeylessCreate2(); 26 | _checkOrDeployInefficientImmutableCreate2Factory(); 27 | _checkOrDeployEfficientImmutableCreate2Factory(); 28 | } 29 | 30 | function _checkOrDeployKeylessCreate2() private { 31 | if (KEYLESS_CREATE2_FACTORY.code.length == 0) { 32 | emit log_string("No Keyless CREATE2 address deployed."); 33 | 34 | if (KEYLESS_CREATE2_DEPLOYER.balance < 0.01 ether) { 35 | emit log_named_address( 36 | "KEYLESS_CREATE2_DEPLOYER does not have sufficient funds. Sending funds to deployer address:", 37 | KEYLESS_CREATE2_DEPLOYER 38 | ); 39 | 40 | (bool success, ) = KEYLESS_CREATE2_DEPLOYER.call{ 41 | value: 0.01 ether 42 | }(""); 43 | if (!success) { 44 | revert("Unable to send funds to KEYLESS_CREATE2_DEPLOYER"); 45 | } 46 | // TODO: fork and wait for block? 47 | } 48 | string[] memory ffiArgs = new string[](2); 49 | ffiArgs[0] = "bash"; 50 | ffiArgs[1] = "submit_presigned_keyless_create.sh"; 51 | bytes memory keylessCreateResult = vm.ffi(ffiArgs); 52 | _checkKeylessCreateResult(keylessCreateResult); 53 | // TODO: fork and wait for block? 54 | } 55 | } 56 | 57 | function _checkOrDeployInefficientImmutableCreate2Factory() private { 58 | if (INEFFICIENT_IMMUTABLE_CREATE2_FACTORY.code.length == 0) { 59 | bytes memory calldata_ = _getCalldata("inefficient_create2"); 60 | (bool success, ) = KEYLESS_CREATE2_FACTORY.call(calldata_); 61 | if (!success) { 62 | revert( 63 | "Unable to deploy INEFFICIENT_IMMUTABLE_CREATE2_FACTORY" 64 | ); 65 | } 66 | // TODO: fork and wait for block? 67 | } 68 | } 69 | 70 | function _checkOrDeployEfficientImmutableCreate2Factory() private { 71 | if (INEFFICIENT_IMMUTABLE_CREATE2_FACTORY.code.length == 0) { 72 | bytes memory calldata_ = _getCalldata("efficient_create2"); 73 | (bool success, ) = INEFFICIENT_IMMUTABLE_CREATE2_FACTORY.call( 74 | calldata_ 75 | ); 76 | if (!success) { 77 | revert("Unable to deploy EFFICIENT_IMMUTABLE_CREATE2_FACTORY"); 78 | } 79 | // TODO: fork and wait for block? 80 | } 81 | } 82 | 83 | function _checkKeylessCreateResult(bytes memory result) private { 84 | // todo: parse and check result of script, currently output is piped to /dev/null 85 | } 86 | 87 | function _getCalldata(string memory fileName) 88 | private 89 | returns (bytes memory) 90 | { 91 | string[] memory ffiArgs = new string[](2); 92 | ffiArgs[0] = "cat"; 93 | ffiArgs[1] = fileName; 94 | return vm.ffi(ffiArgs); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /inefficient_create2_calldata: -------------------------------------------------------------------------------- 1 | 0x608060405234801561001057600080fd5b50610833806100206000396000f3fe60806040526004361061003f5760003560e01c806308508b8f1461004457806364e030871461009857806385cf97ab14610138578063a49a7c90146101bc575b600080fd5b34801561005057600080fd5b506100846004803603602081101561006757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ec565b604080519115158252519081900360200190f35b61010f600480360360408110156100ae57600080fd5b813591908101906040810160208201356401000000008111156100d057600080fd5b8201836020820111156100e257600080fd5b8035906020019184600183028401116401000000008311171561010457600080fd5b509092509050610217565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561014457600080fd5b5061010f6004803603604081101561015b57600080fd5b8135919081019060408101602082013564010000000081111561017d57600080fd5b82018360208201111561018f57600080fd5b803590602001918460018302840111640100000000831117156101b157600080fd5b509092509050610592565b3480156101c857600080fd5b5061010f600480360360408110156101df57600080fd5b508035906020013561069e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b600083606081901c33148061024c57507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008116155b6102a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260458152602001806107746045913960600191505060405180910390fd5b606084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604051855195965090943094508b93508692506020918201918291908401908083835b6020831061033557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016102f8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909216911617905260408051929094018281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00183528085528251928201929092207fff000000000000000000000000000000000000000000000000000000000000008383015260609890981b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602183015260358201969096526055808201979097528251808203909701875260750182525084519484019490942073ffffffffffffffffffffffffffffffffffffffff81166000908152938490529390922054929350505060ff16156104a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603f815260200180610735603f913960400191505060405180910390fd5b81602001825188818334f5955050508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461053a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260468152602001806107b96046913960600191505060405180910390fd5b50505073ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790559392505050565b6000308484846040516020018083838082843760408051919093018181037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001825280845281516020928301207fff000000000000000000000000000000000000000000000000000000000000008383015260609990991b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021820152603581019790975260558088019890985282518088039098018852607590960182525085519585019590952073ffffffffffffffffffffffffffffffffffffffff81166000908152948590529490932054939450505060ff909116159050610697575060005b9392505050565b604080517fff000000000000000000000000000000000000000000000000000000000000006020808301919091523060601b6021830152603582018590526055808301859052835180840390910181526075909201835281519181019190912073ffffffffffffffffffffffffffffffffffffffff81166000908152918290529190205460ff161561072e575060005b9291505056fe496e76616c696420636f6e7472616374206372656174696f6e202d20636f6e74726163742068617320616c7265616479206265656e206465706c6f7965642e496e76616c69642073616c74202d206669727374203230206279746573206f66207468652073616c74206d757374206d617463682063616c6c696e6720616464726573732e4661696c656420746f206465706c6f7920636f6e7472616374207573696e672070726f76696465642073616c7420616e6420696e697469616c697a6174696f6e20636f64652ea265627a7a723058202bdc55310d97c4088f18acf04253db593f0914059f0c781a9df3624dcef0d1cf64736f6c634300050a0032 -------------------------------------------------------------------------------- /efficient_create2_calldata: -------------------------------------------------------------------------------- 1 | 0x64e030870000000000000000000000000000000000000000f4b0218f13a6440a6f02000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000853608060405234801561001057600080fd5b50610833806100206000396000f3fe60806040526004361061003f5760003560e01c806308508b8f1461004457806364e030871461009857806385cf97ab14610138578063a49a7c90146101bc575b600080fd5b34801561005057600080fd5b506100846004803603602081101561006757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166101ec565b604080519115158252519081900360200190f35b61010f600480360360408110156100ae57600080fd5b813591908101906040810160208201356401000000008111156100d057600080fd5b8201836020820111156100e257600080fd5b8035906020019184600183028401116401000000008311171561010457600080fd5b509092509050610217565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561014457600080fd5b5061010f6004803603604081101561015b57600080fd5b8135919081019060408101602082013564010000000081111561017d57600080fd5b82018360208201111561018f57600080fd5b803590602001918460018302840111640100000000831117156101b157600080fd5b509092509050610592565b3480156101c857600080fd5b5061010f600480360360408110156101df57600080fd5b508035906020013561069e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b600083606081901c33148061024c57507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008116155b6102a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260458152602001806107746045913960600191505060405180910390fd5b606084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604051855195965090943094508b93508692506020918201918291908401908083835b6020831061033557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016102f8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909216911617905260408051929094018281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00183528085528251928201929092207fff000000000000000000000000000000000000000000000000000000000000008383015260609890981b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602183015260358201969096526055808201979097528251808203909701875260750182525084519484019490942073ffffffffffffffffffffffffffffffffffffffff81166000908152938490529390922054929350505060ff16156104a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603f815260200180610735603f913960400191505060405180910390fd5b81602001825188818334f5955050508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461053a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260468152602001806107b96046913960600191505060405180910390fd5b50505073ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790559392505050565b6000308484846040516020018083838082843760408051919093018181037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001825280845281516020928301207fff000000000000000000000000000000000000000000000000000000000000008383015260609990991b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021820152603581019790975260558088019890985282518088039098018852607590960182525085519585019590952073ffffffffffffffffffffffffffffffffffffffff81166000908152948590529490932054939450505060ff909116159050610697575060005b9392505050565b604080517fff000000000000000000000000000000000000000000000000000000000000006020808301919091523060601b6021830152603582018590526055808301859052835180840390910181526075909201835281519181019190912073ffffffffffffffffffffffffffffffffffffffff81166000908152918290529190205460ff161561072e575060005b9291505056fe496e76616c696420636f6e7472616374206372656174696f6e202d20636f6e74726163742068617320616c7265616479206265656e206465706c6f7965642e496e76616c69642073616c74202d206669727374203230206279746573206f66207468652073616c74206d757374206d617463682063616c6c696e6720616464726573732e4661696c656420746f206465706c6f7920636f6e7472616374207573696e672070726f76696465642073616c7420616e6420696e697469616c697a6174696f6e20636f64652ea265627a7a723058202bdc55310d97c4088f18acf04253db593f0914059f0c781a9df3624dcef0d1cf64736f6c634300050a003200000000000000000000000000 --------------------------------------------------------------------------------