嘗試拆解Solidity編譯後的bytecode(二)

嘗試拆解Solidity編譯後的bytecode(二)

以下範例皆參考 openzeppelin opcode 的系列文章(共六篇)撰寫。

本篇文章建議有 solidity 開發經驗的讀者閱讀,初學者不適合本篇文章。本文與Solidity opcode基礎有相關性,建議閱讀後再讀本篇文章。

本文與嘗試拆解Solidity編譯後的bytecode(一)有聯貫性,沒有讀過第一篇的讀者大機率看不懂本文!

前情提要

在第一篇文章,我們得知 creation code 是合約的 constructor。合約佈署時,先執行 creation code,執行完成後會返回 runtime code。runtime code代表非 constructor 的程式碼,也就是 developer 寫的各個 function,最終會留在以太鏈的 bytecode。

今天我們就要來了解 runtime code 的「架構」!


前置作業

用 keccak256 算出合約內 3 個 function 的 function signature

  • totalSupply()的function signature:0x18160ddd

  • balanceOf(address)的function signature:0x70a08231

  • transfer(address,uint256)的function signature:0xa9059cbb

專有名詞

  1. Function selector,透過 function signature 選出欲執行的 function,選出後 jump 至 function wrapper

  2. Function wrapper,檢查 function 的 input 參數,檢查後 jump至 function body,執行完 function body後,回傳 return value

  3. Function body,實際執行 function 的程式


執行過程

runtime code編譯後的結果,建議可以再搭配remix debug工具自己執行一次

  1. calldataload 載入calldata(與solidity的calldata只的是一樣的東西)

  2. calldata 會攜帶 function signature,透過 function selector即可解析出該執行哪個function(注意框起來的 16 進制碼,該16進制碼即是各個 function signature。EQ判斷是否mapping成功,成功則執行jump)

  3. 選出執行哪個 function 後 jump 至 function wrapper

  4. function wrapper 檢查完 input 參數後,jump 至 function body

  5. function body 執行完後 jump 回 function wrapper

  6. 在 function wrapper 回傳 return value


Openzeppelin的opcode拆解視覺化圖: https://gists.rawgit.com/ajsantander/23c032ec7a722890feed94d93dff574a/raw/a453b28077e9669d5b51f2dc6d93b539a76834b8/BasicToken.svg

以上可參考openzeppelin提供的opcode拆解視覺化圖及文章開頭的文章,function wrapper和function body建議搭配opcode拆解視覺化圖看較為清楚