5

Solidity Data Collision

 2 years ago
source link: https://medium.com/taipei-ethereum-meetup/solidity-data-collision-51e88f1529a8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Solidity Data Collision

這是一篇關於 Proxy Contract 和 delegatecall 的注意事項。

Delegatecall

當 A 合約對 B 合約執行 delegatecall 時,B 合約的函式會被執行,但是對 storage 的操作都會作用在 A 合約上。舉例如下:

但是假如多加了一個 other 欄位在 _value 之前,執行合約之後反而是 other 欄位被更改了。

Storage Layout

了解上面的合約之前要先了解 Solidity 怎麼儲存 State Variables。Solidity Storage 以 Slot 為單位,每個 Slot 可以儲存 32 bytes 的資訊,一個 Contract 擁有 2**256 個 Slot。上述可以寫成一個映射關係 mapping(uint256 => bytes32) slots

Solidity 會從 Slot Index 為零開始分配給 State Variable。

除了 mappingdynamically-sized array,其他的 State Variable 會從 index 為零的 slot 開始被分配。

沒有宣告確切大小的 Array 會以 Slot Index 計算出一個雜湊值並將其作為 Slot Index。透過計算 keccak256(slot) 可以得知 _arr[0] 被存在哪裡,如果要取得 _arr[1] 則將計算出來的雜湊加上 Array 的 index 即可。

Mapping 則是以 Slot Index 和 Key 計算出一個雜湊值並將其作為 Slot Index。透過計算 keccak256(key, slot) 可以得到 mapping(key => value) 被存在哪。

Storage Collision

回到 DelegateExample_v2 的合約,對 B 來說, add 最後儲存加法的 Slot Index 為零,所以使用 A 的 Storage 執行 B 的函式結果自然會儲存在 A 的 other 裡,其 Slot Index 為 0。

這個問題也發生在 Proxy Contract,Layout 如下,當有需要更改 _owner 的操作,就會順帶把 _implementation 也更改了。

|Proxy                     |Implementation           |
|--------------------------|-------------------------|
|address _implementation |address _owner | <= collision
|... |mapping _balances |
| |uint256 _supply |
| |... |

OpenZeppelin 處理的手法也很簡單,就是將 _implementation 換地方擺。以特定字串的雜湊值作為 Slot Index,儲存 Implementation 的地址。

|Proxy                     |Implementation           |
|--------------------------|-------------------------|
|... |address _owner |
|... |mapping _balances |
|... |uint256 _supply |
|... |... |
|address _implementation | | <= specified
|... | |

hardhat-storage-layout

如何知道合約的 Storage Layout 呢?這邊推薦一個 Hardhat Plugin,按照文件就能得到合約的 Storage Layout。

Reference


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK