引言
在靶场刷题的时候经常会遇到各种涉及到create2
操作码的题,这里整理了两个计算脚本(一个用于创建空参构造器的合约,另一个是用于创建带参构造器的合约),都是基于etherjs-v5
注:脚本只是辅助计算,并不是创建合约,创建合约还得通过智能合约来实现。
空参构造器 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 import { ethers } from "ethers" const const_num = "0xFF" ;const contract_add = "" ;let str1 = const_num + contract_add.slice (2 ,contract_add.length );const bytecode = "" ;const bytecodeToHash = ethers.utils .solidityKeccak256 (['bytes' ],[bytecode]);let salt = 0 ;const value = "" ; while (true ) { let saltToHash = ethers.utils .solidityKeccak256 (['uint' ],[salt]); saltToHash = saltToHash.slice (2 , saltToHash.length ) let str2 = str1.concat (saltToHash).concat (bytecodeToHash.slice (2 ,bytecodeToHash.length )); let hash = ethers.utils .solidityKeccak256 (['bytes' ] ,[str2]); if (hash.slice (hash.length - 2 , hash.length ) == value) { console .log (`salt = ${salt} ` ); console .log (`address = 0x${hash.slice(26 , hash.length)} ` ); break ; } salt++; }
配合使用的solidity代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // /* 使用内联汇编自带的 create2() */ function create2NewContractByInline(uint salt) public returns (address) { // bytes memory code = type(Test).creationCode; // 如果待部署合约的构造器中有参数,则使用如下方式进行获取code bytes memory code = abi.encodePacked(type(Test).creationCode, abi.encode(msg.sender, "biyou")); bytes32 _salt = keccak256(abi.encodePacked(salt)); address result; assembly { result := create2( 0, // value 表示要向新合约发送的以太币数量 add(code, 32), // 表示跳过数组长度 mload(code), // 读取code的长度 _salt // 盐 ) } return result; }
带参构造器 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 import { ethers } from "ethers" const const_num = "0xFF" ;const contract_add = "" ; let str1 = const_num + contract_add.slice (2 ,contract_add.length );let bytecode = "" ;const variable_code = new ethers.utils .AbiCoder ().encode (['type' ], [value]);bytecode = bytecode + variable_code.slice (2 ,variable_code.length ); const bytecodeToHash = ethers.utils .solidityKeccak256 (['bytes' ],[bytecode]);let salt = 0 ;const value = "" ; while (true ) { let saltToHash = ethers.utils .solidityKeccak256 (['uint' ],[salt]); saltToHash = saltToHash.slice (2 , saltToHash.length ) let str2 = str1.concat (saltToHash).concat (bytecodeToHash.slice (2 ,bytecodeToHash.length )); let hash = ethers.utils .solidityKeccak256 (['bytes' ] ,[str2]); if (hash.slice (hash.length - 2 , hash.length ) == value) { console .log (`salt = ${salt} ` ); console .log (`address = 0x${hash.slice(26 , hash.length)} ` ); break ; } salt++; }
配合使用的solidity代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function create2NewContractByInline(uint salt) public returns (address) { /* 如果待部署合约的构造器中有参数,则使用如下方式进行获取code type():待部署的合约名 abi.encode():部署合约需要传入的参数 */ bytes memory code = abi.encodePacked(type().creationCode, abi.encode()); bytes32 _salt = keccak256(abi.encodePacked(salt)); address result; assembly { result := create2( 0, // value 表示要向新合约发送的以太币数量 add(code, 32), // 表示跳过数组长度 mload(code), // 读取code的长度 _salt // 盐 ) } return result; }
补充 以上代码怎么说呢,毕竟是js代码嘛,数字的转化总会有问题,比如算某个地址对某个数取模是否等于某个值之类的,js代码不能轻易实现,反正对我来说不能,于是变自己编写了一个python 版的计算address的脚本。兼容了上述两种情况,完美应对待构建合约空参和有参两种情况。
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 from web3 import Web3from eth_abi import encodeconst_value = "0xff" deployer_address = "" deployer_address = deployer_address[2 :] prefixed = const_value + deployer_address hacker_bytecode = "" parameter = encode(['' ],["" ]).hex () bytecode = "0x" + hacker_bytecode + parameter bytecode_hash = Web3.solidity_keccak(['bytes' ], [bytecode]).hex () i = 0 while (True ): salt = Web3.solidity_keccak(['uint256' ], [i]).hex () data = prefixed + salt[2 :] + bytecode_hash[2 :] hashed = Web3.solidity_keccak(['bytes' ], [data]).hex () address = hashed[26 :] if int (("0x" + address), 16 ) % 1000 == 137 : print ("salt=" , i) print ("address=" , ("0x" + address)) break i += 1
用了都说好!!!
版本 package.json:
1 2 3 4 5 6 { "type" : "module" , "dependencies" : { "ethers" : "^5.7.2" } }