-
Notifications
You must be signed in to change notification settings - Fork 21
/
Factory.sol
68 lines (56 loc) · 2.46 KB
/
Factory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./Attacker.sol";
contract Factory {
// Returns the address of the newly deployed contract
function deploy(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 Attacker{salt: _salt}());
}
}
// This is the older way of doing it using assembly
contract FactoryAssembly {
event Deployed(address addr, uint256 salt);
// 1. Get bytecode of contract to be deployed
function getBytecode() public pure returns (bytes memory) {
bytes memory bytecode = type(Attacker).creationCode;
return abi.encodePacked(bytecode);
}
// 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 Attacker.
// The address in the log should equal the address computed from above.
function deploy(bytes memory bytecode, uint256 _salt) public payable returns (address) {
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);
return addr;
}
}