Solidity
“new Contract()”語法和程序集“create”操作碼之間有什麼區別嗎?
以下兩種通過智能合約創建智能合約的方式有什麼區別嗎?
function create_v1() external { Contract c = new Contract(); }
function create_v2() external { bytes memory deploymentBytecode = type(Contract).creationCode; address contractAddress; assembly { contractAddress := create(0, add(deploymentBytecode, 0x20), mload(deploymentBytecode)) } }
唯一有意義的區別是第一個版本檢查部署是否成功。從返回的地址
create
確實可以是address(0)
,在這種情況下意味著部署失敗(例如Contract
可能在建構子期間恢復)。因此,為了使第二個版本等同於第一個版本,我們可以添加一個簡單的檢查:
function create_v2() external { bytes memory deploymentBytecode = type(Contract).creationCode; address contractAddress; assembly { contractAddress := create(0, add(deploymentBytecode, 0x20), mload(deploymentBytecode)) if iszero(contractAddress) { // we can forward the error message returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } }
提示:檢查solidity在後台做什麼的粗略方法是使用
solc Foo.sol --ir
因為
create_v1
我們可以看到以下內容(改編,評論是我的)function fun_create_v1_16() { let _1 := allocate_unbounded() let _2 := add(_1, datasize("Contract_4")) // Contract_4 is the contract we want to deploy if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() } // memory overflow check datacopy(_1, dataoffset("Contract_4"), datasize("Contract_4")) _2 := abi_encode_tuple__to__fromStack(_2) // does nothing :| let expr_13_address := create(0, _1, sub(_2, _1)) if iszero(expr_13_address) { revert_forward_1() } // check create worked - forward returndata in case let var_c_9_address := expr_13_address }