|
|
|
@ -0,0 +1,98 @@ |
|
|
|
|
// SPDX-License-Identifier: MIT |
|
|
|
|
pragma solidity ^0.8.24; |
|
|
|
|
|
|
|
|
|
// credits to https://solidity-by-example.org/app/create2/ |
|
|
|
|
|
|
|
|
|
contract Create2Factory { |
|
|
|
|
// Returns the address of the newly deployed contract |
|
|
|
|
function deploy(address _owner, uint256 _foo, bytes32 _salt) |
|
|
|
|
public |
|
|
|
|
payable |
|
|
|
|
returns (address) |
|
|
|
|
{ |
|
|
|
|
// This syntax is a newer way to invoke create2 without assembly, you just need to pass salt |
|
|
|
|
// https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2 |
|
|
|
|
return address(new TestContract{salt: _salt}(_owner, _foo)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This is the older way of doing it using assembly |
|
|
|
|
contract Create2FactoryAssembly { |
|
|
|
|
event Deployed(address addr, uint256 salt); |
|
|
|
|
|
|
|
|
|
// 1. Get bytecode of contract to be deployed |
|
|
|
|
// NOTE: _owner and _foo are arguments of the TestContract's constructor |
|
|
|
|
function getBytecode(address _owner, uint256 _foo) |
|
|
|
|
public |
|
|
|
|
pure |
|
|
|
|
returns (bytes memory) |
|
|
|
|
{ |
|
|
|
|
bytes memory bytecode = type(TestContract).creationCode; |
|
|
|
|
|
|
|
|
|
return abi.encodePacked(bytecode, abi.encode(_owner, _foo)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2. Compute the address of the contract to be deployed |
|
|
|
|
// NOTE: _salt is a random number used to create an address |
|
|
|
|
function getAddress(bytes memory bytecode, uint256 _salt) |
|
|
|
|
public |
|
|
|
|
view |
|
|
|
|
returns (address) |
|
|
|
|
{ |
|
|
|
|
bytes32 hash = keccak256( |
|
|
|
|
abi.encodePacked( |
|
|
|
|
bytes1(0xff), address(this), _salt, keccak256(bytecode) |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// NOTE: cast last 20 bytes of hash to address |
|
|
|
|
return address(uint160(uint256(hash))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. Deploy the contract |
|
|
|
|
// NOTE: |
|
|
|
|
// Check the event log Deployed which contains the address of the deployed TestContract. |
|
|
|
|
// The address in the log should equal the address computed from above. |
|
|
|
|
function deploy(bytes memory bytecode, uint256 _salt) public payable { |
|
|
|
|
address addr; |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
NOTE: How to call create2 |
|
|
|
|
|
|
|
|
|
create2(v, p, n, s) |
|
|
|
|
create new contract with code at memory p to p + n |
|
|
|
|
and send v wei |
|
|
|
|
and return the new address |
|
|
|
|
where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[pâ¦(p+n))) |
|
|
|
|
s = big-endian 256-bit value |
|
|
|
|
*/ |
|
|
|
|
assembly { |
|
|
|
|
addr := |
|
|
|
|
create2( |
|
|
|
|
callvalue(), // wei sent with current call |
|
|
|
|
// Actual code starts after skipping the first 32 bytes |
|
|
|
|
add(bytecode, 0x20), |
|
|
|
|
mload(bytecode), // Load the size of code contained in the first 32 bytes |
|
|
|
|
_salt // Salt from function arguments |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if iszero(extcodesize(addr)) { revert(0, 0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
emit Deployed(addr, _salt); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
contract TestContract { |
|
|
|
|
address public owner; |
|
|
|
|
uint256 public foo; |
|
|
|
|
|
|
|
|
|
constructor(address _owner, uint256 _foo) payable { |
|
|
|
|
owner = _owner; |
|
|
|
|
foo = _foo; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getBalance() public view returns (uint256) { |
|
|
|
|
return address(this).balance; |
|
|
|
|
} |
|
|
|
|
} |