Repository navigation
Expand file tree
/
Copy pathStorageVar.sol
More file actions
146 lines (110 loc) · 3.37 KB
/
Copy pathStorageVar.sol
File metadata and controls
146 lines (110 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract StorageVars {
uint x;
uint y;
uint z;
// gas : 75225
function foo() public {
y = 2; // (SSTORE 0x01, 0x02)
z = 3; // (SSTORE 0x02, 0x03)
}
function bar() external view returns (uint) {
return y ; // SLOAD 0x01 , MSTORE ..., RETURN
}
}
contract StorageCompact {
uint8 x; // slot 0
uint8 y; // slot 0
function foo() public returns (uint8) {
uint8 sum = x + y;
return sum;
}
// gas : 50242
function bar() public {
x = 1;
y = 2;
}
}
contract StorageStruct {
// slot 0
uint z;
struct Point {
uint8 x;
uint8 y;
uint8 z;
}
// slot 1
Point p;
function foo() public view returns (uint8) {
uint8 sum = p.x + p.y + p.z;
return sum;
}
}
contract StorageMapping {
mapping(address => uint) public x;
function foo(address a, address b) public {
x[a] = 1; // slot = keccak256(abi.encode(key, slot_x))
x[b] = 2; // slot = keccak256(abi.encode(key, slot_x))
}
function getMappingSlot(address key) public pure returns (bytes32) {
uint256 slot = 0; // 假设 mapping 声明在槽位 0
return keccak256(abi.encode(key, slot));
}
function getValueAtKey(address key) public view returns (uint256 value) {
bytes32 slot = getMappingSlot(key);
assembly {
value := sload(slot)
}
}
// 0x0000000000000000000000000000000000000000000000000000000000000000
function getValueAtSlot(bytes32 slot) public view returns (uint256 value) {
assembly {
value := sload(slot)
}
}
}
contract StorageArray {
uint a; // slot 0
uint[2] public b; // slot 1, 2
uint[] public c; // slot 3 // save length, 元素数据存储的起始位置是:keccak256(slot)
uint32[2] public d; // slot 4
function foo() public {
b[0] = 1;
b[1] = 2;
c.push(3);
c.push(4);
d[0] = 1;
d[1] = 2;
}
function getArraySlotStart() public pure returns (bytes32) {
uint256 slot = 3; // 动态 array 声明在槽位 3
return keccak256(abi.encode(slot));
}
function getValueAtIndex(uint index) public view returns (uint256 value) {
bytes32 slot = bytes32(uint256(getArraySlotStart()) + index);
assembly {
value := sload(slot)
}
}
function getValueAtSlot(bytes32 slot) public view returns (bytes32 value) {
assembly {
value := sload(slot)
}
}
}
contract StorageString {
string public a = "short"; // slot 0 少于 31 字节 // cast from-utf8 "short" 0x73686f7274
string public b = "too too too too too too too too too too too too too too long"; // slot 1
// cast from-utf8 "too too too too too too too too too too too too too too long"
// 0x746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f20746f6f206c6f6e67
function getArraySlotStart() public pure returns (bytes32) {
uint256 slot = 1; // 动态 array 声明在槽位 1
return keccak256(abi.encode(slot));
}
function getValueAtSlot(bytes32 slot) public view returns (bytes32 value) {
assembly {
value := sload(slot)
}
}
}