Fork me on GitHub
pikachu's Blog

Create2

前言

  • 智能合约生成合约地址的第二种方式 Create2
  • 以一道例题解释
  • 计算地址有两种方式

    • Create : keccak256(rlp.encode(deployingAddress, nonce))[12:]
    • Create2 : keccak256(0xff ++ deployingAddr ++ salt ++ keccak256(bytecode))[12:]
  • 关于 Create2 ,这里就不介绍了,可以参考 EIP 1014: CREATE2 指令

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
pragma solidity ^0.4.21;

interface IName {
function name() external view returns (bytes32);
}

contract FuzzyIdentityChallenge {
bool public isComplete;

function authenticate() public {
require(isSmarx(msg.sender));
require(isBadCode(msg.sender));

isComplete = true;
}

function isSmarx(address addr) internal view returns (bool) {
return IName(addr).name() == bytes32("smarx");
}

function isBadCode(address _addr) internal pure returns (bool) {
bytes20 addr = bytes20(_addr);
bytes20 id = hex"000000000000000000000000000000000badc0de";
bytes20 mask = hex"000000000000000000000000000000000fffffff";

for (uint256 i = 0; i < 34; i++) {
if (addr & mask == id) {
return true;
}
mask <<= 4;
id <<= 4;
}

return false;
}
}
  • 很简单,要求 namesmarx ,并且 msg.sender 包含 badc0de ,可通过下面合约解决,只需要合约地址包括 badc0de 即可
1
2
3
4
5
6
7
8
9
pragma solidity ^0.5.12;
contract BadCodeSmarx is IName {
function callAuthenticate(address _challenge) public {
FuzzyIdentityChallenge(_challenge).authenticate();
}
function name() external view returns (bytes32) {
return bytes32("smarx");
}
}
  • Create2 方法解决,如下,我们只需要计算出相对应的 salt 即可, Deployer 被部署在 0xca4dfd86a86c48c5d9c228bedbeb7f218a29c94b
1
2
3
4
5
6
7
8
9
10
11
12
13
contract Deployer {
// contractBytecode是待部署合约的bytecode
bytes contractBytecode = hex"608060405234801561001057600080fd5b5061015d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806306fdde031461003b5780637872ab4914610059575b600080fd5b61004361009d565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561006f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100c5565b005b60007f736d617278000000000000000000000000000000000000000000000000000000905090565b8073ffffffffffffffffffffffffffffffffffffffff1663380c7a676040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561010d57600080fd5b505af1158015610121573d6000803e3d6000fd5b505050505056fea265627a7a72315820fb2fc7a07f0eebf799c680bb1526641d2d905c19393adf340a04e48c9b527de964736f6c634300050c0032";

function deploy(bytes32 salt) public {
bytes memory bytecode = contractBytecode;
address addr;

assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
}
}
}
  • 写了一个脚本爆破 salt, 只要包含 badc0de 即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from web3 import Web3

s1 = '0xffca4dfd86a86c48c5d9c228bedbeb7f218a29c94b'

s3 = '4670da3f633e838c2746ca61c370ba3dbd257b86b28b78449f4185480e2aba51'

i = 0
while(1):
salt = hex(i)[2:].rjust(64, '0')
s = s1+salt+s3
hashed = Web3.sha3(hexstr=s)
hashed_str = ''.join(['%02x' % b for b in hashed])
if 'badc0de' in hashed_str[24:]:
print(salt,hashed_str)
break
i += 1
print(salt)
  • 结果如下

  • 最后调用 Deployer.deploy(0x00...005b2bfe) 即可把 BadCodeSmarx 合约部署到地址 0xa905a3922a4ebfbc7d257cecdb1df04a3badc0de

  • 也有大佬通过 Create 方式解决的,有兴趣的可以参考 https://www.anquanke.com/post/id/154104#h3-11 , 带佬自行验证
    ,我没有验证

---------------- The End ----------------
谢谢大爷~

Author:pikachu
Link:https://hitcxy.com/2020/Create2/
Contact:hitcxy@hotmail.com
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!