Solidity

合約呼叫的輸出是如何編碼的?

  • April 28, 2021

嗨,我有一個代理合約 A,它使用標準 OpenZeppelin 程式碼將函式執行委託給實現合約 B:

assembly {
           calldatacopy(0, 0, calldatasize())


           let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)

           // Copy the returned data.
           returndatacopy(0, 0, returndatasize())

           switch result
           // delegatecall returns 0 on error.
           case 0 { revert(0, returndatasize()) }
           default { return(0, returndatasize()) }
       }

當我嘗試呼叫函式 getter 以獲得應該是[10, 100]我得到字元串的結果時0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000064。這是什麼編碼以及我可以使用哪個庫來解碼它。起初我以為是 RLP 編碼,但我檢查了一些 RLP 解碼器,但沒有檢查出來。謝謝

這是 Solidity 使用的 ABI 編碼格式,記錄在Contract ABI Specification中。基本上,靜態值(例如,數字、布爾值、bytes1..32)被編碼為 32 個字節(64 個十六進製字元),而動態值在最後被編碼,其中指向位置的指針被編碼到位。

以您的結果為例,首先將其分成 32 個字節的組。

0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
000000000000000000000000000000000000000000000000000000000000000a
0000000000000000000000000000000000000000000000000000000000000064

由於輸出是一個數組,前 32 個字節0x000...0200x20這第二組 32 字節指定了數組的長度,在這種情況下0x2或簡稱為 2,這意味著接下來的兩組 32 字節是數組的一部分。

正如預期的那樣,最後兩組0x0a0x64分別為 10 和 100,因此解碼輸出結果[10, 100]符合預期。

當然,手動執行此操作效率不高,並且有一些庫可以自動為您解析輸出。假設您使用的是 JavaScript/TypeScript:

還有一些線上工具可用於編碼和解碼:

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