Skip to content

Commit

Permalink
feat: simplify bootstrap code and remove PUSH0 usage
Browse files Browse the repository at this point in the history
  • Loading branch information
dyedm1 committed Oct 7, 2023
1 parent a290cee commit dd7a899
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 38 deletions.
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,17 @@
### Initcode for address derivation

For `Create4Factory`, the `initCode` is constructed as follows:
- Code segment 1: `5f5f5f5f5f73`
- `Create4Factory` address: `ffffffffffffffffffffffffffffffffffffffff`
- Code segment 2: `5af13d5f5f3e3d5ff3`
- Deployer address (user calling `create4`): `ffffffffffffffffffffffffffffffffffffffff`
- Executable constructor: `3636363636335af13d36363e3d36f3`
- Deployer address (user calling `create4`): `ffffffffffffffffffffffffffffffffffffffff` (20-byte salt)

Result: `0x5f5f5f5f5f73<Create4Factory address>5af13d5f5f3e3d5ff3<deployer address>`
Result: `0x3636363636335af13d36363e3d36f3<deployer address>`
#### Example
If we have
- `Create4Factory` address: `0xe358511cd9bf45c8a4d4aaf96ad5f6234ad20282` (note: not the real-world address!)
- Deployer address: `0xab5801a7d398351b8be11c439e05c5b3259aec9b` (Vb)

Our `initCode` would be:
`0x5f5f5f5f5f73e358511cd9bf45c8a4d4aaf96ad5f6234ad202825af13d5f5f3e3d5ff3ab5801a7d398351b8be11c439e05c5b3259aec9b`
`0x3636363636335af13d36363e3d36f3ab5801a7d398351b8be11c439e05c5b3259aec9b`

### Features

Expand Down
47 changes: 18 additions & 29 deletions src/Create4Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,27 @@ pragma solidity ^0.8.20;
*/
contract Create4Factory {
/*
[26 BYTES]
PUSH0 // retSize: 0
PUSH0 // retOffset: 0
PUSH0 // argsSize: 0
PUSH0 // argsOffset: 0
PUSH0 // value: 0
PUSH20 (0x0000000000000000000000000000000000000000) // FACTORY ADDRESS(THIS), FILLED DYNAMICALLY
Right-padded with 0s to 32 bytes
*/
bytes32 internal constant BOOTSTRAP_CODE_SECTION_1 =
hex"5f5f5f5f5f73000000000000000000000000000000000000000000000000";

/*
[29 BYTES]
[35 BYTES]
CALLDATASIZE // retSize: 0
CALLDATASIZE // retOffset: 0
CALLDATASIZE // argsSize: 0
CALLDATASIZE // argsOffset: 0
CALLDATASIZE // value: 0
CALLER // Create4Factory
GAS // gas (gas remaining in frame)
CALL
RETURNDATASIZE // size (of returned code to copy)
PUSH0 // offset: 0
PUSH0 // destOffset: 0
CALLDATASIZE // offset: 0
CALLDATASIZE // destOffset: 0
RETURNDATACOPY
RETURNDATASIZE // size (of code to return/deploy)
PUSH0 // offset: 0
CALLDATASIZE // offset: 0
RETURN
(0x0000000000000000000000000000000000000000) // MSG.SENDER, FILLED DYNAMICALLY (appended for frontrunning protection)
Right-padded with 0s to 32 bytes
*/
bytes32 internal constant BOOTSTRAP_CODE_SECTION_2 =
hex"5af13d5f5f3e3d5ff30000000000000000000000000000000000000000000000";
bytes32 internal constant BOOTSTRAP_CODE = hex"3636363636335af13d36363e3d36f30000000000000000000000000000000000";


uint256 internal constant UINT256_MAX = 2 ** 256 - 1;

Expand Down Expand Up @@ -66,12 +59,10 @@ contract Create4Factory {
currentDeployment = deployedCode;

assembly {
mstore(0, BOOTSTRAP_CODE_SECTION_1)
mstore(6, shl(96, address()))
mstore(26, BOOTSTRAP_CODE_SECTION_2)
mstore(35, shl(96, caller()))
mstore(0, BOOTSTRAP_CODE)
mstore(15, shl(96, caller()))

newContract := create2(0, 0, 55, salt)
newContract := create2(0, 0, 35, salt)
}
}

Expand Down Expand Up @@ -101,12 +92,10 @@ contract Create4Factory {
tstore(i, mload(add(deployedCode, add(32, mul(i, 32)))))
}

mstore(0, BOOTSTRAP_CODE_SECTION_1)
mstore(6, shl(96, address()))
mstore(26, BOOTSTRAP_CODE_SECTION_2)
mstore(35, shl(96, caller()))
mstore(0, BOOTSTRAP_CODE)
mstore(15, shl(96, caller()))

newContract := create2(0, 0, 55, salt)
newContract := create2(0, 0, 35, salt)
}
}

Expand Down
5 changes: 2 additions & 3 deletions test/Create4Factory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ import {Test, console2} from "forge-std/Test.sol";
import {Create4Factory} from "src/Create4Factory.sol";

contract TestCreate4Factory is Test {
bytes6 internal constant BOOTSTRAP_CODE_SECTION_1 = hex"5f5f5f5f5f73";
bytes9 internal constant BOOTSTRAP_CODE_SECTION_2 = hex"5af13d5f5f3e3d5ff3";
bytes15 internal constant BOOTSTRAP_CODE = hex"3636363636335af13d36363e3d36f3";
address internal constant EIP_1153_MAGIC = address(0x4549502d31313533);

Create4Factory internal C4F;

function expectedAddress(address deployer, bytes32 salt) internal view returns (address) {
bytes32 bootstrapCodeHash = keccak256(
abi.encodePacked(
BOOTSTRAP_CODE_SECTION_1, bytes20(address(C4F)), BOOTSTRAP_CODE_SECTION_2, bytes20(address(deployer))
BOOTSTRAP_CODE, bytes20(address(deployer))
)
);

Expand Down

0 comments on commit dd7a899

Please sign in to comment.