用 Slither 在合約升級之前做檢查
Published in
7 min readJun 25, 2022
Slither 是 Solidity 的靜態分析器,由資安公司 trait of bits 開發,用以檢查合約漏洞。本篇文章以 slither 裡面的 tool slither-check-upgradeability 做 upgradeable contract 的檢查,以避免合約升級出現問題。
Installation
安裝 slither 即可,slither-check-upgradeability 也會同時安裝進去
pip3 install slither-analyzer
或是使用 docker,然後將合約透過 volume 掛進去
docker pull trailofbits/eth-security-toolbox
Usage
可升級合約要升級時,這時候的 codebase 則應該要有三個合約,Proxy, LogicContract_V1 和 LogicContract_V2 三個,範例合約如下:
這邊的合約都有問題,檢查 storage collision 時,可以抓出以下問題:
- Proxy 跟兩個 Logic Contract 之間:範例中,V1, V2 都和 Proxy 有 storage collision 的問題
- Logic Contract 之間:V1, V2 中 _val 變數存在不同的 slot 裡面
使用 slither-check-upgradeability 檢查
如果使用像是 OpenZeppelin 等套件,則需要帶入 remappings 進去。這是讓 solc compiler 可以知道引入的 solidity 檔案位於何處。一般使用 hardhat 等 framework 會幫你設定好 remappings 讓 solc 知道從 node_modules 抓。
以下為範例:
- 檢查 V1 升級至 V2 有沒有漏洞
# bash
slither-check-upgradeability \
./LogicV1.sol LogicV1 \
--new-contract-filename ./LogicV2.sol \
--new-contract-name LogicV2 \
--solc-remaps '@openzeppelin/=lib/openzeppelin-contracts/'
輸出如下,V1._val 和 V2._a 位在同樣的 slot 上但卻是不同的變數名稱
INFO:Slither:
Different variables between LogicV1 (src/LogicV1.sol#4-11) and LogicV2 (src/LogicV2.sol#4-12)
LogicV1._val (src/LogicV1.sol#5)
LogicV2._a (src/LogicV2.sol#5)
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#incorrect-variables-with-the-v2
- 檢查 V1 跟 Proxy
# bash
slither-check-upgradeability \
./LogicV1.sol LogicV1 \
--proxy-filename ./Proxy.sol \
--proxy-name SampleProxy \
--solc-remaps '@openzeppelin/=lib/openzeppelin-contracts/'
輸出如下,V1._val 和 Proxy._addr 位在同樣的 slot 上但卻是不同的變數名稱
INFO:Slither:
Different variables between LogicV1 (src/LogicV1.sol#4-11) and SampleProxy (src/upgrade/Proxy.sol#6-16)
LogicV1._val (src/LogicV1.sol#5)
SampleProxy._addr (src/upgrade/Proxy.sol#7)
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#incorrect-variables-with-the-proxy
- 也同時檢查 V1, V2 和 Proxy
# bash
slither-check-upgradeability \
./LogicV1.sol LogicV1 \
--new-contract-filename ./LogicV2.sol \
--new-contract-name LogicV2 \
--proxy-filename ./Proxy.sol \
--proxy-name SampleProxy \
--solc-remaps '@openzeppelin/=lib/openzeppelin-contracts/'
以下為 V1-V2,V1-Proxy 和 V2-Proxy 檢查的輸出
INFO:Slither:
Different variables between LogicV1 (src/LogicV1.sol#4-11) and SampleProxy (src/upgrade/Proxy.sol#6-16)
LogicV1._val (src/LogicV1.sol#5)
SampleProxy._addr (src/upgrade/Proxy.sol#7)
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#incorrect-variables-with-the-proxy
INFO:Slither:
Different variables between LogicV2 (src/LogicV2.sol#4-12) and SampleProxy (src/upgrade/Proxy.sol#6-16)
LogicV2._a (src/LogicV2.sol#5)
SampleProxy._addr (src/upgrade/Proxy.sol#7)
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#incorrect-variables-with-the-proxy
INFO:Slither:
Different variables between LogicV1 (src/LogicV1.sol#4-11) and LogicV2 (src/LogicV2.sol#4-12)
LogicV1._val (src/LogicV1.sol#5)
LogicV2._a (src/LogicV2.sol#5)
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#incorrect-variables-with-the-v2