智能合约生成合约地址的第二种方式 Create2
以一道例题解释
计算地址有两种方式
Create : keccak256(rlp.encode(deployingAddress, nonce))[12:]
Create2 : keccak256(0xff ++ deployingAddr ++ salt ++ keccak256(bytecode))[12:]
关于 Create2 ,这里就不介绍了,可以参考 EIP 1014: CREATE2 指令
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;
}
}
很简单,要求 name 是 smarx ,并且 msg.sender 包含 badc0de ,可通过下面合约解决,只需要合约地址包括 badc0de 即可
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
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 即可
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)
结果如下