Solidity

“new Contract()”語法和程序集“create”操作碼之間有什麼區別嗎?

  • August 17, 2022

以下兩種通過智能合約創建智能合約的方式有什麼區別嗎?

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
}

引用自:https://ethereum.stackexchange.com/questions/133782