Solidity

EVM 如何辨識函式 calldata 中的動態類型?

  • October 21, 2020

因此,根據 Solidity Docs 中提到的 ABI 編碼規範,對於動態數組,首先指定數據位置(以字節為單位,用於數據部分),然後是先前指定位置的數組長度,然後是由實際數據值。

文件中的範例:

要呼叫的函式:function sam(bytes memory, bool, uint[] memory) public pure {}

sam (“dave”, true,$$ 1, 2, 3 $$) :

0xa5643bf2 00000000000000000000000000000000000000000000000000000000000060 000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0 0000000000000000000000000000000000000000000000000000000000000004 646176650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

這裡,第一組粗體字節表示“dave”字節值的位置。第二組粗體值是實際數據(從數據的長度開始,這裡是 4)。

那麼,在解釋 calldata 時,EVM 與動態數據的位置和普通變數值有何不同?即在這裡,如何將 0x00…60 標識為位置值,而不是可能是靜態 uint?

回答我自己的問題。

所以,我顯然錯過了 abi-encoding 函式遵循頭尾編碼機制的事實。然後,abi-decoding 函式跟踪參數類型——實際上它檢查數據類型是否具有預定義的大小,如果沒有,則將手頭的值視為起始位置。

是decode_abi的一個非常清晰的pyethereum實現。

這是函式的神奇部分:

for i, typ in enumerate(types):
   if sizes[i] is None:
       start_positions[i] = big_endian_to_int(data[pos:pos + 32])
       j = i - 1
       while j >= 0 and start_positions[j] is None:
           start_positions[j] = start_positions[i]
           j -= 1
       pos += 32
   else:
       outs[i] = data[pos:pos + sizes[i]]
       pos += sizes[i]

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