Solidity
呼叫外部函式時何時使用 .call 和 abi.encodeWithSignature 何時不使用
誰能告訴我為什麼有時當你想呼叫外部合約上的函式(下面的第一個範例)時你必須使用 .call 方法和 abi.encodeWithSignature ,而其他時候你可以簡單地呼叫帶有參數的合約 name.function (下面的第二個例子)。
除了明顯的區別之外,一個在建構子中,一個在函式中被讚賞?
使用 .call 方法的契約…
pragma solidity 0.8.13; contract callerContract{ address payable targetAddress = payable(0x3328358128832A260C76A4141e19E2A943CD4B6D); bytes public result; constructor() payable{} function callExternal(uint256 _number) public{ (bool success, bytes memory returnData) = targetAddress.call{value: 100, gas: 10000}(abi.encodeWithSignature("targetFunction(uint256)",_number)); result = returnData; } }
使用合約 name.functionName 呼叫函式的合約,帶有值和函式參數(沒有 .call 方法,也沒有 abiEncodeWithSignature 來訪問此處需要的函式) 我指的是 gateway.depositETH … 等。
pragma solidity ^0.7.5; import "./IERC20.sol"; import "./IWETHGateway.sol"; contract Escrow { address arbiter; address depositor; address beneficiary; uint initialDeposit; IWETHGateway gateway = IWETHGateway(0xDcD33426BA191383f1c9B431A342498fdac73488); IERC20 aWETH = IERC20(0x030bA81f1c18d280636F32af80b9AAd02Cf0854e); constructor(address _arbiter, address _beneficiary) payable { arbiter = _arbiter; beneficiary = _beneficiary; depositor = msg.sender; initialDeposit = msg.value; gateway.depositETH{value: address(this).balance}(address(this), 0); }
使用呼叫時,需要在被呼叫的合約上指定目標函式。因此,編碼函式簽名
(abi.encodeWithSignature("targetFunction(uint256)"
後跟作為參數傳遞的值(在本例中為“uint”,_number)。編碼指定由其函式簽名呼叫的函式。你可以在這裡得到更多
第一種方法稱為“低級呼叫”。它通常用於節省通話費用或處理回复。
例子:
// this is a low level call (bool success, bytes memory returndata) = token.call(abi.encodeWithSignature(IERC20.transfer.selector, to, value)); // this is a normal call IERC20(token).transfer(to, value); // this is a how a normal call works using low-level call require(token.code.size > 0); (bool success, bytes memory returndata) = token.call(abi.encodeWithSignature(IERC20.transfer.selector, to, value)); require(success); // ... also forwards the error message
基本上,正常的呼叫會自動添加對合約是否存在以及呼叫是否成功的檢查。使用低級呼叫,您可以跳過這些檢查以節省燃料。