用 Slither 在合約升級之前做檢查

Wias Liaw
Taipei Ethereum Meetup
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_V1LogicContract_V2 三個,範例合約如下:

這邊的合約都有問題,檢查 storage collision 時,可以抓出以下問題:

  1. Proxy 跟兩個 Logic Contract 之間:範例中,V1, V2 都和 Proxy 有 storage collision 的問題
  2. 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

--

--