Skip to content

Instantly share code, notes, and snippets.

@imqdee
Last active June 5, 2023 11:14
Show Gist options
  • Select an option

  • Save imqdee/ffb2dcc9e7285c673299be918ea3bab1 to your computer and use it in GitHub Desktop.

Select an option

Save imqdee/ffb2dcc9e7285c673299be918ea3bab1 to your computer and use it in GitHub Desktop.
contract Deployer {
event Deployed(address);
// This is the runtime code of the contract we would like to deploy
// Example: `contract DummyContract { uint256 public nonce; }`
bytes CONTRACT_RUNTIME_CODE =
hex"6080604052348015600e575f80fd5b50600436106026575f3560e01c8063affed0e014602a575b5f80fd5b60315f5481565b60405190815260200160405180910390f3";
// This handmade creation code is responsible of returning the creation code of dynamic length
// ⚠️ It assumes the contract we would like to deploy doesn't have a constructor (!!)
// ℹ️ If the size of the precompile is fixed, we can simplify the sequence
bytes constant CREATION_CODE = hex"80_60_0E_60_00_39_60_00_F3";
/*
0x00 0x63 0x63XXXXXX PUSH4 _code.length size
0x01 0x80 0x80 DUP1 size size
0x02 0x60 0x600e PUSH1 14 14 size size
0x03 0x60 0x6000 PUSH1 00 0 14 size size
0x04 0x39 0x39 CODECOPY size
0x05 0x60 0x6000 PUSH1 00 0 size
0x06 0xf3 0xf3 RETURN
<CODE>
*/
function deploy(bytes calldata precompile) external returns (address addr) {
uint256 finalRuntimeCodeLength = CONTRACT_RUNTIME_CODE.length + precompile.length;
bytes memory bytecode = abi.encodePacked(
hex"63", // PUSH4
uint32(finalRuntimeCodeLength), // <length>
// responsible of returning the dynamic runtime code
CREATION_CODE,
// concatenation of both runtime code
bytes.concat(CONTRACT_RUNTIME_CODE, precompile)
);
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
// if the `create` opcode fails, the address is equals to 0
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(addr);
}
function deploy(bytes calldata precompile, bytes32 salt)
external
returns (address addr)
{
uint256 finalRuntimeCodeLength = CONTRACT_RUNTIME_CODE.length + precompile.length;
bytes memory bytecode = abi.encodePacked(
hex"63", // PUSH4
uint32(finalRuntimeCodeLength), // <length>
// responsible of returning the dynamic runtime code
CREATION_CODE,
// concatenation of both runtime code
bytes.concat(CONTRACT_RUNTIME_CODE, precompile)
);
assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
// if the `create` opcode fails, the address is equals to 0
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(addr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment