iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Modern Web

web3 短篇集系列 第 2

認識 Calldata

  • 分享至 

  • xImage
  •  

首先介紹 signature vs. selector:

  • function signature: ex. setNumber(uint256)
  • function selector (function method identifier): ex. 0x3fb5c1cb

假設在 solidity 有一個 function 是:

function transfer(address to, uint256 amount) public virtual returns (bool) { ... }

那它的 function signature 為 transfer(address,uint256)。沒有空格,也沒有 function 開頭。

對 function sginature 做 keccak-256 hash 後可以得到 32 bytes 如下:

0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b

transfer(address,uint256) 的 function selector 是 hash 後的前四個 bytes,也就是:0xa9059cbb

--

ABI encoding 是以太坊上的編碼格式,當我們要呼叫合約時,要先把函式名稱與參數編譯成 calldata 後,才能用來呼叫合約。

要使用一個合約呼叫另一個合約上的 function,寫法如下:

targetContractAddress.call(abi.encodeWithSignature("setNumber(uint256)", 32);

abi.encodeWithSignature 會回傳 calldata,長得像這樣:

0x3fb5c1cb0000000000000000000000000000000000000000000000000000000000000018

--

calldata 可以用來呼叫合約,也可能是一筆鏈上交易的 input data,它需經過 ABI encoding 後得到。calldata 的前四個 bytes 也就是 function selector,而之後所接的可能是 arguments, offset, length 等等。

假設我們對以下函式名稱與參數進行 ABI encoding:

transfer(uint256[],address)
transfer([5769, 14894, 7854], 0x1b7e1b7ea98232c77f9efc75c4a7c7ea2c4d79f1)

cast calldata

cast calldata "transfer(uint256[],address)" "[5769, 14894, 7854]" 0x1b7e1b7ea98232c77f9efc75c4a7c7ea2c4d79f1

得到的 calldata 如下:

0x8229ffb6 // function selector
0000000000000000000000000000000000000000000000000000000000000040 // offset
0000000000000000000000001b7e1b7ea98232c77f9efc75c4a7c7ea2c4d79f1 // address
0000000000000000000000000000000000000000000000000000000000000003 // length
0000000000000000000000000000000000000000000000000000000000001689
0000000000000000000000000000000000000000000000000000000000003a2e
0000000000000000000000000000000000000000000000000000000000001eae

offset: 用來標示 dynamic data 的位置,是以 offset 提供的位置起算。

--

Fixed-sized data types in solidity:

  • bool
  • uints
  • bytes of fixed size (byteN)
  • address
  • tuple, struct with fixed data
  • fixed-size array

Dynamic data types:

  • bytes
  • string
  • dynamic array
  • a fixed-size array that contains dynamic types
  • a struct that contains any of the above dynamic types

使用 dynamic data 的 calldata 較為複雜,因為會有 offset,可以參考這篇文章,從 Working with dynamic calldata 的標題開始,會帶你拆解 calldata 看懂 offset。

https://www.rareskills.io/post/abi-encoding

建議搭配文末留言提供的 ABI CallData Visualizer,它能夠更清楚呈現 calldata 的樣貌。

PS: calldata 的長度會影響交易的 gas 成本,計算方式如下:

  • a non-zero byte: 16 gas
  • a zero bytes: 4 gas

因為 zero byte 比較便宜,有些人會刻意將合約的地址創造成前面有很多個零,當這個地址作為參數放在 calldata 時就會比較便宜。


上一篇
前言
下一篇
使用 Foundry 學習 Solidity
系列文
web3 短篇集30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言