Solidity

如果合約方法的實際返回數據類型不同於 ABI 會發生什麼

  • October 22, 2022

假設我們要處理 ERC-20 代幣,但有些代幣合約並不完全符合標準。在 IERC20 介面中,transfer有如下簽名。

function transfer(address to, uint value) external returns (bool);

在solidity程式碼中,我們可以像這樣呼叫合約的方法:

bool success = IERC20(tokenAddress).transfer(to, value)

我的問題是,

  1. 如果合約的 transfer 方法沒有返回任何東西會發生什麼。
  • 呼叫transfer最終恢復?
  • 或者將空值分配給布爾變數會導致還原?
  • 或者它不會恢復並且分配了一些值?
  1. 如果合約的 transfer 方法返回另一個數據類型的值,例如uint
  • 將 uint 值分配給布爾變數會導致還原?
  • 或者它不會恢復並且分配了一些值?

嘿再次哈哈 :) 這很容易測試,但是是的,在這兩種情況下呼叫都會恢復(當執行跳回你的合約並檢查返回數據時)

我做了一些實驗,發現了以下內容。

transfer呼叫令牌合約的方法時,它會返回一個bytes. 我們可以使用以下程式碼查看數據。

(bool success, bytes memory data) = token.call(abi.encodeWithSignature('transfer(address,uint256)', to, value));
  • 數據長度為32字節的倍數
  • 小位長度數據(例如 uint160 或 bool)被 0 填充到 32 字節
  • 例如uint[3]有 96 字節長度
  • 如果傳遞函式不返回任何內容,則字節長度為 0

當我們呼叫像這樣的合約方法IERC20(tokenAddress).transfer(to, value)時,返回值是基於IERC20介面解析的。transfer假設IERC20 介面中函式的返回類型為bool. 然後來自函式呼叫的數據像這樣解碼。

abi.decode(data, (bool))

如果數據長度為 32 字節且值為 0 或 1,則此解碼有效。

關於我的問題Q1,它恢復了,因為獲得的數據的長度為0,無法解碼為bool。

對於問題Q2,除非返回值為0或1,否則它會恢復。(例如,假設有一個ERC20合約實現了transfer返回類型為0或1的函式。那麼uint數據可以解碼為bool。因此呼叫不恢復

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