Solidity 及 EVM 開發工具介紹

NIC Lin
Taipei Ethereum Meetup
14 min readNov 1, 2022

這篇文章將介紹 Ethereum 開發者的一些實用工具:Foundry 除了測試之外的功能及 VSCode 的 Solidity Visual Developer 插件

Photo by Dan Cristian Pădureț on Unsplash

Foundry

Foundry 除了提供合約開發、測試和部署,其實還有許多其他實用的功能。

安裝 Foundry

如果是 Linux 或 macOS,先安裝 foundryup,接著直接用 foundryup 指令就可以安裝。未來要升級 foundry 也只需要執行 foundryup 就好,非常簡單直覺。

// Install foundryup
curl -L https://foundry.paradigm.xyz | bash

// Install or update Foundry
foundryup

詳細可以參考 Foundry book 的 Installation 頁面

Auto Completion

Foundry 安裝完後會有 forgecastanvil 三個指令,每個指令也都有許多 option,這時有 Auto Completion 會非常省事。例如產生 bash 用的 Auto Completion script:

mkdir -p $HOME/.local/share/bash-completion/completions
forge completions bash > $HOME/.local/share/bash-completion/completions/forge
cast completions bash > $HOME/.local/share/bash-completion/completions/cast
anvil completions bash > $HOME/.local/share/bash-completion/completions/anvil
exec bash

其他 Shell script 的產生方式可以參考 Foundry book 的 Shell Autocompletion 頁面

anvil

其實就和 Ganache 及 hardhat node 一樣:跑起一個節點。可以是全新的一個本地節點,也可以是背後連上 Forked State(例如 Forked Mainnet、Forked Goerli)的節點。如果你平常都是習慣用來跑一個短暫的全新測試節點就直接下 anvil 即可。

如果你會想在一個 Forked State 內實驗或測試的話,多加上 --fork-url--fork-block-number 的 option。另外可以留意 --compute-units-per-second 這個 option,它會控制每秒請求的計算量,避免取 Forked State 太頻繁導致遇到像是 Alchemy Rate Limit 的問題。

更詳細的節點設置可以參考 Foundry book 的 Anvil Reference 頁面

cast

cast 是用來取鏈上資料非常好用的工具(也有送交易的工具但個人覺得不太實用)。因為有很多功能,這裡我只會列出我常用及覺得實用的功能。

註:要讀取鏈的狀態記得要在 foundry.toml 檔裡附上 endpoint url(eth_rpc_url=$URL)或透過 --rpc-url $URL 的方式。

首先是抓取交易資訊:

  • cast tx/receipt抓取交易receipt 資訊
  • cast run印出一筆已被收入的交易的 execution trace 或進行 live debug(加上 --debug option),為了得到準確的交易前狀態,預設會模擬執行同一區塊裡在該筆交易前面所有的交易,但這可能很耗時,如果只想看交易執行過程且不需要最精準的執行結果的話,可以加上 --quick option,它會跳過前面交易的模擬,直接把該筆交易當作區塊的第一筆交易來執行

註:cast run --debug 的 debug 介面可能沒有那麼好讀,如果不需要看到執行過程中的 memory/stack/storage 等細節時可以直接用 ethtx.infoTenderly ,好讀很多。

cast tx $TX_HASH
cast receipt $TX_HASH
cast run $TX_HASH --quick --debug

接著是從 Etherscan 抓取合約資訊:

// Download WETH9 contract file to tmp folder
cast etherscan-source -d tmp 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 --etherscan-api-key $API_KEY

註:如果想直接在瀏覽器開啟 VSCode 環境來瀏覽、編輯合約的話,可以使用 deth.net。還可以透過書籤一鍵開啟,非常方便,請參考這則 twitter

接著是 encode/decode ABI 的功能:

註:因為 function selector 只有 4 bytes,如果多個 function signature 都是同一個 function selector 的話,則反查會回傳所有可能 function signature

// Decode function selector of "transfer(address,uint256)"
cast 4b 0xa9059cbb
// Decode calldata of a transfer
cast 4bd 0xa9059cbb000000000000000000000000f8ed47951b8eb0997d9f038fb1fcea46b171ea2f0000000000000000000000000000000000000000000000000000000078ca2e7e
// Decode event signature of "Transfer(address,address,uint256)"
cast 4be 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
// Encode calldata for a transfer
cast calldata "transfer(address,uint256)" 0xf8ed47951B8eB0997D9F038FB1FCea46B171Ea2f 2026516094

最後是一些轉換或計算的小工具:

cast --from-utf8 "pls return my money"
// 0x706c732072657475726e206d79206d6f6e6579

cast --to-ascii 0x706c732072657475726e206d79206d6f6e6579
// "pls return my money"

cast sig "transfer(address,uint256)"
// 0xa9059cbb

cast keccak "transfer(address,uint256)"
// 0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b

cast compute-address 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --nonce 123
// Computed Address: 0xB57130C323EC5A53F89b73c9cA6f9Fc3c11744f6

更多 cast 功能可以參考 Foundry book 的 cast Commands 頁面。你可以從中按照你的需求找到對你有幫助的常用指令。

forge inspect

forge 的 inspect 指令則是用來挖出一個合約更進階的資訊。它不是去拉鏈上的資料,而是作用在本地端的檔案(例如 MyContract),所以如果你需要分析(鏈上的)其他合約,你需要先把它下載下來。

forge inspect MyContract ...

註:在分析前 forge 會先編譯合約,會花一些時間。

首先是列出合約基本資料的功能:

  • forge inspect MyContract abi/bytecode/deployedBytecode:列出 MyContract的 ABI/編譯完的 bytecode/實際部署到鏈上後的 bytecode,方便 export ABI 或是比對部署在鏈上的 bytecode
  • forge inspect MyContract methods/gas:列出 MyContract的(public 的) function 列表(包含 function signature 及 selector)/ 每個 function 的預估 gas 消耗 。用 cast 4b/4bd 其實就能反查特定 function selector,這個功能比較像是能看到一個合約完整的 function 資訊
  • forge inspect MyContract storage:列出 MyContract的 storage,包含每個變數的 storage slotoffset(如果有多個變數被 pack 在一起的話,offset 會是每個變數在該 slot 的起始位置)。但呈現的資料比較醜一點,可以改用 slither 來分析合約 storage 或讀取合約變數的值,它還可以拉鏈上的合約來分析,不需要先下載合約下來。

接下來是比較進階的使用:irOptimized(或 iro),主要是你想再優化你合約的 gas 消耗時可以採用的方式。

forge inspect MyContract irOptimized

它會呈現你的合約編譯成(優化過的)Yul 後的長相。Yul 就像 assembly,它介於 Solidity 和 EVM opcode 之間,它可以讓你看到你寫的 Solidity function 背後實際上還做了哪些事情,如此你就可以開始刪去一些不需要的檢查。

這個工具是從這兩則 twitter(link1, link2)發現到的,這邊直接引用裡面的範例和圖片來搭配說明。以一個簡單的將 number 變數遞增的 Counter 合約為例,裡面有一個 setNumber 函式用來設置 number 的值及一個 increment 函式用來把 number1。右邊則是執行 forge inspect Counter irOptimized 後所輸出 Yul 版本的 Counter 合約:

source: https://twitter.com/w1nt3r_eth/status/1579486967963693057

可以看到一個簡單的 Solidity 合約編譯完後變得複雜許多。接下來以 increment 函式為例:

source: https://twitter.com/w1nt3r_eth/status/1579486967963693057

可以發現一個 number++ 裡面其實包含了很多檢查,例如 not payable 和 overflow。但其實我們知道它只會以一次加 1 的方式遞增所以幾乎不可能會 overflow(加上 unchecked),然後如果這個函式是可以接受 ether 的話,那就可以再省掉 not payable 的檢查(加上 payable):

source: https://twitter.com/w1nt3r_eth/status/1579486967963693057

可以發現省去了許多執行步驟。

比起原地把 Solidity 程式碼替換成 assembly 程式碼這種比較冒險的優化方式,這是一個新的管道讓你能重新完整地檢視你的合約,並且可以看出修改前後的對比。但要注意還是以安全為優先,不要為了省一點的 gas 而拿掉你沒有把握的程式碼或檢查。

其他 forge inspect 功能可以參考 Foundry book 的 forge inspect 頁面

VSCode

最後是介紹一個在 review 合約時很實用的 VSCode 插件:Solidity Visual Developer

註:以下介紹會是個人使用心得,所以會有特色或功能是沒有介紹到的。可以自己下載來試用看看,看能不能發現適合你的用途的功能。

裡面最常看到的就是它為你合約的變數套上框框並能連結到宣告變數的地方,以及函式的參數套上底色方便識別(雖然有時候顏色太多會看得有點眼花)。另外有 variable shadowing 的警告提醒,例如你的合約繼承了 Ownable 合約但某個函式宣告了一個 owner 參數,這時候這個 owner 參數就會被套上顯眼的紅色框框來提醒你:

owner 變數被 owner 參數 shadow 了

keywords 例如 block.timestamptx.originmsg.data 或是 external 等等關鍵字都有提供 hover 時顯示安全提醒:

block.timestamp 的安全提醒
external 的安全提醒

如果你在 review 合約需要做筆記時,可以利用 @audit@audit-ok 這兩個 tag,它會出現像 Bookmarks 那樣的圖示方便你回到筆記過的程式碼段落:

@audit 及 @audit-ok 分別顯示紅色及綠色的書籤圖示

它還有提供一些分析整個合約的功能,讓你能得到不同合約間的繼承關係(inheritance)和函式之間的關係(graph),這邊直接使用官方的圖:

https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor
https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor

還有其他工具像是 flatten:

Solidity Visual Developer 這個插件對 review 或審計合約算是非常有幫助,但寫合約時幫助比較少。雖然對一般人來說裡面大部分的工具其實平常幾乎都用不太到,不過至少知道有哪些工具可以使用之後,未來有天當你需要 review 合約的時候它們就可以派上用場。

--

--

No responses yet