Solidity
使用 Assembly 訪問狀態變數
我用彙編做了一些實驗,不幸的是,沒有太多的文件,其中大多數都涵蓋了相同的主題(數學運算、extcodesize 等)。在這裡,我試圖讀取我的狀態變數,當我只有一個變數時它可以工作,但似乎不再是多個變數的情況了。
指針似乎指向錯誤的地方,所以我測試了不同的方法
pragma solidity ^0.8.0; contract Assembly { bool private var1 = true; bool private var2 = false; uint8 private var3 = 8; function getThirdVariable() public view returns(uint8 res, uint8 res2, uint8 res3, uint8 res4) { assembly { res := var3.slot res2 := var3.offset res3 := sload(var3.slot) res4 := sload(var3.offset) } } }
這是我的函式的返回:
uint8: res 0 uint8: res2 2 uint8: res3 1 uint8: res4 0
任何幫助將不勝感激
這是因為狀態變數在可能的情況下被打包在儲存槽中。
您的變數在 storage 中具有以下大小:
boolean : 1 byte uint8 : 1 byte
假設一個儲存槽是 32 字節,它們三個都可以放入第一個槽 (0)。
您可以使用此功能進行檢查:
function getSlots() public view returns (uint256, uint256, uint256) { uint256 slotVar1; uint256 slotVar2; uint256 slotVar3; assembly { slotVar1 := var1.slot slotVar2 := var2.slot slotVar3 := var3.slot } return (slotVar1, slotVar2, slotVar3); // 0, 0, 0 }
現在,因為它們被打包在同一個插槽中,所以它們不能具有相同的偏移量:
function getOffsets() public view returns (uint256, uint256, uint256) { uint256 offsetVar1; uint256 offsetVar2; uint256 offsetVar3; assembly { offsetVar1 := var1.offset offsetVar2 := var2.offset offsetVar3 := var3.offset } return (offsetVar1, offsetVar2, offsetVar3); // 0, 1, 2 }
值槽 0 本身反映了這一點:
0x0000000000000000000000000000000000000000000000000000000000000080001
其中字節 0:0x01 是 var 1(布爾真),字節 1:0x00 是 var 2(布爾假),字節 2:0x08 是 var 3(uint8 8)。
要獲取第三個變數,您需要從
var3.slot
偏移量開始的儲存槽中的 1 個字節var3.offset
:function getThirdVariable() public view returns(uint8) { uint8 value; assembly { let tmp := sload(var3.slot) // get the value at var3.slot tmp := shr(mul(var3.offset, 8), tmp) // shift that value by var3.offset * 8 bits to the right value := tmp // store the result for return } return value; // 8 }