Solidity
如果合約方法的實際返回數據類型不同於 ABI 會發生什麼
假設我們要處理 ERC-20 代幣,但有些代幣合約並不完全符合標準。在 IERC20 介面中,
transfer
有如下簽名。function transfer(address to, uint value) external returns (bool);
在solidity程式碼中,我們可以像這樣呼叫合約的方法:
bool success = IERC20(tokenAddress).transfer(to, value)
我的問題是,
- 如果合約的 transfer 方法沒有返回任何東西會發生什麼。
- 呼叫
transfer
最終恢復?- 或者將空值分配給布爾變數會導致還原?
- 或者它不會恢復並且分配了一些值?
- 如果合約的 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。因此呼叫不恢復)