Solidity

呼叫外部函式時何時使用 .call 和 abi.encodeWithSignature 何時不使用

  • September 21, 2022

誰能告訴我為什麼有時當你想呼叫外部合約上的函式(下面的第一個範例)時你必須使用 .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

基本上,正常的呼叫會自動添加對合約是否存在以及呼叫是否成功的檢查。使用低級呼叫,您可以跳過這些檢查以節省燃料。

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