@godzillaba/mutest 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/Dockerfile +117 -0
- package/.devcontainer/devcontainer.json +62 -0
- package/.devcontainer/init-firewall.sh +118 -0
- package/.github/workflows/test.yml +38 -0
- package/.gitmodules +3 -0
- package/CLAUDE.md +39 -0
- package/README.md +33 -0
- package/foundry.lock +8 -0
- package/foundry.toml +6 -0
- package/index.ts +97 -0
- package/lib/forge-std/.gitattributes +1 -0
- package/lib/forge-std/.github/CODEOWNERS +1 -0
- package/lib/forge-std/.github/dependabot.yml +6 -0
- package/lib/forge-std/.github/workflows/ci.yml +125 -0
- package/lib/forge-std/.github/workflows/sync.yml +36 -0
- package/lib/forge-std/CONTRIBUTING.md +193 -0
- package/lib/forge-std/LICENSE-APACHE +203 -0
- package/lib/forge-std/LICENSE-MIT +25 -0
- package/lib/forge-std/README.md +314 -0
- package/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
- package/lib/forge-std/foundry.toml +18 -0
- package/lib/forge-std/package.json +16 -0
- package/lib/forge-std/scripts/vm.py +636 -0
- package/lib/forge-std/src/Base.sol +48 -0
- package/lib/forge-std/src/Config.sol +60 -0
- package/lib/forge-std/src/LibVariable.sol +477 -0
- package/lib/forge-std/src/Script.sol +28 -0
- package/lib/forge-std/src/StdAssertions.sol +779 -0
- package/lib/forge-std/src/StdChains.sol +303 -0
- package/lib/forge-std/src/StdCheats.sol +825 -0
- package/lib/forge-std/src/StdConfig.sol +632 -0
- package/lib/forge-std/src/StdConstants.sol +30 -0
- package/lib/forge-std/src/StdError.sol +15 -0
- package/lib/forge-std/src/StdInvariant.sol +140 -0
- package/lib/forge-std/src/StdJson.sol +275 -0
- package/lib/forge-std/src/StdMath.sol +47 -0
- package/lib/forge-std/src/StdStorage.sol +475 -0
- package/lib/forge-std/src/StdStyle.sol +333 -0
- package/lib/forge-std/src/StdToml.sol +275 -0
- package/lib/forge-std/src/StdUtils.sol +200 -0
- package/lib/forge-std/src/Test.sol +32 -0
- package/lib/forge-std/src/Vm.sol +2533 -0
- package/lib/forge-std/src/console.sol +1551 -0
- package/lib/forge-std/src/console2.sol +4 -0
- package/lib/forge-std/src/interfaces/IERC1155.sol +105 -0
- package/lib/forge-std/src/interfaces/IERC165.sol +12 -0
- package/lib/forge-std/src/interfaces/IERC20.sol +43 -0
- package/lib/forge-std/src/interfaces/IERC4626.sol +190 -0
- package/lib/forge-std/src/interfaces/IERC6909.sol +72 -0
- package/lib/forge-std/src/interfaces/IERC721.sol +164 -0
- package/lib/forge-std/src/interfaces/IERC7540.sol +144 -0
- package/lib/forge-std/src/interfaces/IERC7575.sol +241 -0
- package/lib/forge-std/src/interfaces/IMulticall3.sol +68 -0
- package/lib/forge-std/src/safeconsole.sol +13248 -0
- package/lib/forge-std/test/CommonBase.t.sol +44 -0
- package/lib/forge-std/test/Config.t.sol +381 -0
- package/lib/forge-std/test/LibVariable.t.sol +452 -0
- package/lib/forge-std/test/StdAssertions.t.sol +141 -0
- package/lib/forge-std/test/StdChains.t.sol +227 -0
- package/lib/forge-std/test/StdCheats.t.sol +638 -0
- package/lib/forge-std/test/StdConstants.t.sol +38 -0
- package/lib/forge-std/test/StdError.t.sol +119 -0
- package/lib/forge-std/test/StdJson.t.sol +49 -0
- package/lib/forge-std/test/StdMath.t.sol +202 -0
- package/lib/forge-std/test/StdStorage.t.sol +485 -0
- package/lib/forge-std/test/StdStyle.t.sol +110 -0
- package/lib/forge-std/test/StdToml.t.sol +49 -0
- package/lib/forge-std/test/StdUtils.t.sol +342 -0
- package/lib/forge-std/test/Vm.t.sol +18 -0
- package/lib/forge-std/test/compilation/CompilationScript.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationScriptBase.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationTest.sol +8 -0
- package/lib/forge-std/test/compilation/CompilationTestBase.sol +8 -0
- package/lib/forge-std/test/fixtures/broadcast.log.json +187 -0
- package/lib/forge-std/test/fixtures/config.toml +81 -0
- package/lib/forge-std/test/fixtures/test.json +8 -0
- package/lib/forge-std/test/fixtures/test.toml +6 -0
- package/package.json +10 -0
- package/script/Counter.s.sol +19 -0
- package/src/Counter.sol +14 -0
- package/test/Counter.t.sol +24 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
2
|
+
pragma solidity >=0.8.13 <0.9.0;
|
|
3
|
+
|
|
4
|
+
import {stdStorage, StdStorage} from "../src/StdStorage.sol";
|
|
5
|
+
import {Test} from "../src/Test.sol";
|
|
6
|
+
|
|
7
|
+
contract StdStorageTest is Test {
|
|
8
|
+
using stdStorage for StdStorage;
|
|
9
|
+
|
|
10
|
+
StorageTest internal test;
|
|
11
|
+
|
|
12
|
+
function setUp() public {
|
|
13
|
+
test = new StorageTest();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function test_StorageHidden() public {
|
|
17
|
+
assertEq(uint256(keccak256("my.random.var")), stdstore.target(address(test)).sig("hidden()").find());
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function test_StorageObvious() public {
|
|
21
|
+
assertEq(uint256(0), stdstore.target(address(test)).sig("exists()").find());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function test_StorageExtraSload() public {
|
|
25
|
+
assertEq(16, stdstore.target(address(test)).sig(test.extra_sload.selector).find());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function test_StorageCheckedWriteHidden() public {
|
|
29
|
+
stdstore.target(address(test)).sig(test.hidden.selector).checked_write(100);
|
|
30
|
+
assertEq(uint256(test.hidden()), 100);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function test_StorageCheckedWriteObvious() public {
|
|
34
|
+
stdstore.target(address(test)).sig(test.exists.selector).checked_write(100);
|
|
35
|
+
assertEq(test.exists(), 100);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function test_StorageCheckedWriteSignedIntegerHidden() public {
|
|
39
|
+
stdstore.target(address(test)).sig(test.hidden.selector).checked_write_int(-100);
|
|
40
|
+
assertEq(int256(uint256(test.hidden())), -100);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function test_StorageCheckedWriteSignedIntegerObvious() public {
|
|
44
|
+
stdstore.target(address(test)).sig(test.tG.selector).checked_write_int(-100);
|
|
45
|
+
assertEq(test.tG(), -100);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function test_StorageMapStructA() public {
|
|
49
|
+
uint256 slot =
|
|
50
|
+
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).find();
|
|
51
|
+
assertEq(uint256(keccak256(abi.encode(address(this), 4))), slot);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function test_StorageMapStructB() public {
|
|
55
|
+
uint256 slot =
|
|
56
|
+
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).find();
|
|
57
|
+
assertEq(uint256(keccak256(abi.encode(address(this), 4))) + 1, slot);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function test_StorageDeepMap() public {
|
|
61
|
+
uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this))
|
|
62
|
+
.with_key(address(this)).find();
|
|
63
|
+
assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function test_StorageCheckedWriteDeepMap() public {
|
|
67
|
+
stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(address(this))
|
|
68
|
+
.checked_write(100);
|
|
69
|
+
assertEq(100, test.deep_map(address(this), address(this)));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function test_StorageDeepMapStructA() public {
|
|
73
|
+
uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
|
74
|
+
.with_key(address(this)).depth(0).find();
|
|
75
|
+
assertEq(
|
|
76
|
+
bytes32(
|
|
77
|
+
uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0
|
|
78
|
+
),
|
|
79
|
+
bytes32(slot)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function test_StorageDeepMapStructB() public {
|
|
84
|
+
uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
|
85
|
+
.with_key(address(this)).depth(1).find();
|
|
86
|
+
assertEq(
|
|
87
|
+
bytes32(
|
|
88
|
+
uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1
|
|
89
|
+
),
|
|
90
|
+
bytes32(slot)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function test_StorageCheckedWriteDeepMapStructA() public {
|
|
95
|
+
stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
|
96
|
+
.with_key(address(this)).depth(0).checked_write(100);
|
|
97
|
+
(uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
|
|
98
|
+
assertEq(100, a);
|
|
99
|
+
assertEq(0, b);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function test_StorageCheckedWriteDeepMapStructB() public {
|
|
103
|
+
stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
|
104
|
+
.with_key(address(this)).depth(1).checked_write(100);
|
|
105
|
+
(uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
|
|
106
|
+
assertEq(0, a);
|
|
107
|
+
assertEq(100, b);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function test_StorageCheckedWriteMapStructA() public {
|
|
111
|
+
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).checked_write(100);
|
|
112
|
+
(uint256 a, uint256 b) = test.map_struct(address(this));
|
|
113
|
+
assertEq(a, 100);
|
|
114
|
+
assertEq(b, 0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function test_StorageCheckedWriteMapStructB() public {
|
|
118
|
+
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).checked_write(100);
|
|
119
|
+
(uint256 a, uint256 b) = test.map_struct(address(this));
|
|
120
|
+
assertEq(a, 0);
|
|
121
|
+
assertEq(b, 100);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function test_StorageStructA() public {
|
|
125
|
+
uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(0).find();
|
|
126
|
+
assertEq(uint256(7), slot);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function test_StorageStructB() public {
|
|
130
|
+
uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(1).find();
|
|
131
|
+
assertEq(uint256(7) + 1, slot);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function test_StorageCheckedWriteStructA() public {
|
|
135
|
+
stdstore.target(address(test)).sig(test.basic.selector).depth(0).checked_write(100);
|
|
136
|
+
(uint256 a, uint256 b) = test.basic();
|
|
137
|
+
assertEq(a, 100);
|
|
138
|
+
assertEq(b, 1337);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function test_StorageCheckedWriteStructB() public {
|
|
142
|
+
stdstore.target(address(test)).sig(test.basic.selector).depth(1).checked_write(100);
|
|
143
|
+
(uint256 a, uint256 b) = test.basic();
|
|
144
|
+
assertEq(a, 1337);
|
|
145
|
+
assertEq(b, 100);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function test_StorageMapAddrFound() public {
|
|
149
|
+
uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find();
|
|
150
|
+
assertEq(uint256(keccak256(abi.encode(address(this), uint256(1)))), slot);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function test_StorageMapAddrRoot() public {
|
|
154
|
+
(uint256 slot, bytes32 key) =
|
|
155
|
+
stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).parent();
|
|
156
|
+
assertEq(address(uint160(uint256(key))), address(this));
|
|
157
|
+
assertEq(uint256(1), slot);
|
|
158
|
+
slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).root();
|
|
159
|
+
assertEq(uint256(1), slot);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function test_StorageMapUintFound() public {
|
|
163
|
+
uint256 slot = stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).find();
|
|
164
|
+
assertEq(uint256(keccak256(abi.encode(100, uint256(2)))), slot);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function test_StorageCheckedWriteMapUint() public {
|
|
168
|
+
stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).checked_write(100);
|
|
169
|
+
assertEq(100, test.map_uint(100));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function test_StorageCheckedWriteMapAddr() public {
|
|
173
|
+
stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).checked_write(100);
|
|
174
|
+
assertEq(100, test.map_addr(address(this)));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function test_StorageCheckedWriteMapBool() public {
|
|
178
|
+
stdstore.target(address(test)).sig(test.map_bool.selector).with_key(address(this)).checked_write(true);
|
|
179
|
+
assertTrue(test.map_bool(address(this)));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function testFuzz_StorageCheckedWriteMapPacked(address addr, uint128 value) public {
|
|
183
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_lower.selector).with_key(addr)
|
|
184
|
+
.checked_write(value);
|
|
185
|
+
assertEq(test.read_struct_lower(addr), value);
|
|
186
|
+
|
|
187
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_upper.selector).with_key(addr)
|
|
188
|
+
.checked_write(value);
|
|
189
|
+
assertEq(test.read_struct_upper(addr), value);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function test_StorageCheckedWriteMapPackedFullSuccess() public {
|
|
193
|
+
uint256 full = test.map_packed(address(1337));
|
|
194
|
+
// keep upper 128, set lower 128 to 1337
|
|
195
|
+
full = (full & (uint256((1 << 128) - 1) << 128)) | 1337;
|
|
196
|
+
stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337)))
|
|
197
|
+
.checked_write(full);
|
|
198
|
+
assertEq(1337, test.read_struct_lower(address(1337)));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function test_RevertStorageConst() public {
|
|
202
|
+
StorageTestTarget target = new StorageTestTarget(test);
|
|
203
|
+
|
|
204
|
+
vm.expectRevert("stdStorage find(StdStorage): No storage use detected for target.");
|
|
205
|
+
target.expectRevertStorageConst();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function testFuzz_StorageNativePack(uint248 val1, uint248 val2, bool boolVal1, bool boolVal2) public {
|
|
209
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.tA.selector).checked_write(val1);
|
|
210
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.tB.selector).checked_write(boolVal1);
|
|
211
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.tC.selector).checked_write(boolVal2);
|
|
212
|
+
stdstore.enable_packed_slots().target(address(test)).sig(test.tD.selector).checked_write(val2);
|
|
213
|
+
|
|
214
|
+
assertEq(test.tA(), val1);
|
|
215
|
+
assertEq(test.tB(), boolVal1);
|
|
216
|
+
assertEq(test.tC(), boolVal2);
|
|
217
|
+
assertEq(test.tD(), val2);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function test_StorageReadBytes32() public {
|
|
221
|
+
bytes32 val = stdstore.target(address(test)).sig(test.tE.selector).read_bytes32();
|
|
222
|
+
assertEq(val, hex"1337");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function test_StorageReadBool_False() public {
|
|
226
|
+
bool val = stdstore.target(address(test)).sig(test.tB.selector).read_bool();
|
|
227
|
+
assertEq(val, false);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function test_StorageReadBool_True() public {
|
|
231
|
+
bool val = stdstore.target(address(test)).sig(test.tH.selector).read_bool();
|
|
232
|
+
assertEq(val, true);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function test_RevertIf_ReadingNonBoolValue() public {
|
|
236
|
+
vm.expectRevert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
|
|
237
|
+
this.readNonBoolValue();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function readNonBoolValue() public {
|
|
241
|
+
stdstore.target(address(test)).sig(test.tE.selector).read_bool();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function test_StorageReadAddress() public {
|
|
245
|
+
address val = stdstore.target(address(test)).sig(test.tF.selector).read_address();
|
|
246
|
+
assertEq(val, address(1337));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function test_StorageReadUint() public {
|
|
250
|
+
uint256 val = stdstore.target(address(test)).sig(test.exists.selector).read_uint();
|
|
251
|
+
assertEq(val, 1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function test_StorageReadInt() public {
|
|
255
|
+
int256 val = stdstore.target(address(test)).sig(test.tG.selector).read_int();
|
|
256
|
+
assertEq(val, type(int256).min);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function testFuzz_Packed(uint256 val, uint8 elemToGet) public {
|
|
260
|
+
// This function tries an assortment of packed slots, shifts meaning number of elements
|
|
261
|
+
// that are packed. Shiftsizes are the size of each element, i.e. 8 means a data type that is 8 bits, 16 == 16 bits, etc.
|
|
262
|
+
// Combined, these determine how a slot is packed. Making it random is too hard to avoid global rejection limit
|
|
263
|
+
// and make it performant.
|
|
264
|
+
|
|
265
|
+
// change the number of shifts
|
|
266
|
+
for (uint256 i = 1; i < 5; i++) {
|
|
267
|
+
uint256 shifts = i;
|
|
268
|
+
|
|
269
|
+
elemToGet = uint8(bound(elemToGet, 0, shifts - 1));
|
|
270
|
+
|
|
271
|
+
uint256[] memory shiftSizes = new uint256[](shifts);
|
|
272
|
+
for (uint256 j; j < shifts; j++) {
|
|
273
|
+
shiftSizes[j] = 8 * (j + 1);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
test.setRandomPacking(val);
|
|
277
|
+
|
|
278
|
+
uint256 leftBits;
|
|
279
|
+
uint256 rightBits;
|
|
280
|
+
for (uint256 j; j < shiftSizes.length; j++) {
|
|
281
|
+
if (j < elemToGet) {
|
|
282
|
+
leftBits += shiftSizes[j];
|
|
283
|
+
} else if (elemToGet != j) {
|
|
284
|
+
rightBits += shiftSizes[j];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// we may have some right bits unaccounted for
|
|
289
|
+
leftBits += 256 - (leftBits + shiftSizes[elemToGet] + rightBits);
|
|
290
|
+
// clear left bits, then clear right bits and realign
|
|
291
|
+
uint256 expectedValToRead = (val << leftBits) >> (leftBits + rightBits);
|
|
292
|
+
|
|
293
|
+
uint256 readVal = stdstore.target(address(test)).enable_packed_slots()
|
|
294
|
+
.sig("getRandomPacked(uint8,uint8[],uint8)").with_calldata(abi.encode(shifts, shiftSizes, elemToGet))
|
|
295
|
+
.read_uint();
|
|
296
|
+
|
|
297
|
+
assertEq(readVal, expectedValToRead);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function testFuzz_Packed2(uint256 nvars, uint256 seed) public {
|
|
302
|
+
// Number of random variables to generate.
|
|
303
|
+
nvars = bound(nvars, 1, 20);
|
|
304
|
+
|
|
305
|
+
// This will decrease as we generate values in the below loop.
|
|
306
|
+
uint256 bitsRemaining = 256;
|
|
307
|
+
|
|
308
|
+
// Generate a random value and size for each variable.
|
|
309
|
+
uint256[] memory vals = new uint256[](nvars);
|
|
310
|
+
uint256[] memory sizes = new uint256[](nvars);
|
|
311
|
+
uint256[] memory offsets = new uint256[](nvars);
|
|
312
|
+
|
|
313
|
+
for (uint256 i = 0; i < nvars; i++) {
|
|
314
|
+
// Generate a random value and size.
|
|
315
|
+
offsets[i] = i == 0 ? 0 : offsets[i - 1] + sizes[i - 1];
|
|
316
|
+
|
|
317
|
+
uint256 nvarsRemaining = nvars - i;
|
|
318
|
+
uint256 maxVarSize = bitsRemaining - nvarsRemaining + 1;
|
|
319
|
+
sizes[i] = bound(uint256(keccak256(abi.encodePacked(seed, i + 256))), 1, maxVarSize);
|
|
320
|
+
bitsRemaining -= sizes[i];
|
|
321
|
+
|
|
322
|
+
uint256 maxVal;
|
|
323
|
+
uint256 varSize = sizes[i];
|
|
324
|
+
assembly {
|
|
325
|
+
// mask = (1 << varSize) - 1
|
|
326
|
+
maxVal := sub(shl(varSize, 1), 1)
|
|
327
|
+
}
|
|
328
|
+
vals[i] = bound(uint256(keccak256(abi.encodePacked(seed, i))), 0, maxVal);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Pack all values into the slot.
|
|
332
|
+
for (uint256 i = 0; i < nvars; i++) {
|
|
333
|
+
stdstore.enable_packed_slots().target(address(test)).sig("getRandomPacked(uint256,uint256)")
|
|
334
|
+
.with_key(sizes[i]).with_key(offsets[i]).checked_write(vals[i]);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Verify the read data matches.
|
|
338
|
+
for (uint256 i = 0; i < nvars; i++) {
|
|
339
|
+
uint256 readVal = stdstore.enable_packed_slots().target(address(test))
|
|
340
|
+
.sig("getRandomPacked(uint256,uint256)").with_key(sizes[i]).with_key(offsets[i]).read_uint();
|
|
341
|
+
|
|
342
|
+
uint256 retVal = test.getRandomPacked(sizes[i], offsets[i]);
|
|
343
|
+
|
|
344
|
+
assertEq(readVal, vals[i]);
|
|
345
|
+
assertEq(retVal, vals[i]);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function testEdgeCaseArray() public {
|
|
350
|
+
stdstore.target(address(test)).sig("edgeCaseArray(uint256)").with_key(uint256(0)).checked_write(1);
|
|
351
|
+
assertEq(test.edgeCaseArray(0), 1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
contract StorageTestTarget {
|
|
356
|
+
using stdStorage for StdStorage;
|
|
357
|
+
|
|
358
|
+
StdStorage internal stdstore;
|
|
359
|
+
StorageTest internal test;
|
|
360
|
+
|
|
361
|
+
constructor(StorageTest test_) {
|
|
362
|
+
test = test_;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function expectRevertStorageConst() public {
|
|
366
|
+
stdstore.target(address(test)).sig("const()").find();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
contract StorageTest {
|
|
371
|
+
uint256 public exists = 1;
|
|
372
|
+
mapping(address => uint256) public map_addr;
|
|
373
|
+
mapping(uint256 => uint256) public map_uint;
|
|
374
|
+
mapping(address => uint256) public map_packed;
|
|
375
|
+
mapping(address => UnpackedStruct) public map_struct;
|
|
376
|
+
mapping(address => mapping(address => uint256)) public deep_map;
|
|
377
|
+
mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
|
|
378
|
+
UnpackedStruct public basic;
|
|
379
|
+
|
|
380
|
+
uint248 public tA;
|
|
381
|
+
bool public tB;
|
|
382
|
+
|
|
383
|
+
bool public tC = false;
|
|
384
|
+
uint248 public tD = 1;
|
|
385
|
+
|
|
386
|
+
struct UnpackedStruct {
|
|
387
|
+
uint256 a;
|
|
388
|
+
uint256 b;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
mapping(address => bool) public map_bool;
|
|
392
|
+
|
|
393
|
+
bytes32 public tE = hex"1337";
|
|
394
|
+
address public tF = address(1337);
|
|
395
|
+
int256 public tG = type(int256).min;
|
|
396
|
+
bool public tH = true;
|
|
397
|
+
bytes32 private tI = ~bytes32(hex"1337");
|
|
398
|
+
|
|
399
|
+
uint256 randomPacking;
|
|
400
|
+
|
|
401
|
+
// Array with length matching values of elements.
|
|
402
|
+
uint256[] public edgeCaseArray = [3, 3, 3];
|
|
403
|
+
|
|
404
|
+
constructor() {
|
|
405
|
+
basic = UnpackedStruct({a: 1337, b: 1337});
|
|
406
|
+
|
|
407
|
+
uint256 two = (1 << 128) | 1;
|
|
408
|
+
map_packed[msg.sender] = two;
|
|
409
|
+
map_packed[address(uint160(1337))] = 1 << 128;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function read_struct_upper(address who) public view returns (uint256) {
|
|
413
|
+
return map_packed[who] >> 128;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function read_struct_lower(address who) public view returns (uint256) {
|
|
417
|
+
return map_packed[who] & ((1 << 128) - 1);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function hidden() public view returns (bytes32 t) {
|
|
421
|
+
bytes32 slot = keccak256("my.random.var");
|
|
422
|
+
assembly ("memory-safe") {
|
|
423
|
+
t := sload(slot)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function const() public pure returns (bytes32 t) {
|
|
428
|
+
t = bytes32(hex"1337");
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function extra_sload() public view returns (bytes32 t) {
|
|
432
|
+
// trigger read on slot `tE`, and make a staticcall to make sure compiler doesn't optimize this SLOAD away
|
|
433
|
+
assembly {
|
|
434
|
+
pop(staticcall(gas(), sload(tE.slot), 0, 0, 0, 0))
|
|
435
|
+
}
|
|
436
|
+
t = tI;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function setRandomPacking(uint256 val) public {
|
|
440
|
+
randomPacking = val;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function _getMask(uint256 size) internal pure returns (uint256 mask) {
|
|
444
|
+
assembly {
|
|
445
|
+
// mask = (1 << size) - 1
|
|
446
|
+
mask := sub(shl(size, 1), 1)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function setRandomPacking(uint256 val, uint256 size, uint256 offset) public {
|
|
451
|
+
// Generate mask based on the size of the value
|
|
452
|
+
uint256 mask = _getMask(size);
|
|
453
|
+
// Zero out all bits for the word we're about to set
|
|
454
|
+
uint256 cleanedWord = randomPacking & ~(mask << offset);
|
|
455
|
+
// Place val in the correct spot of the cleaned word
|
|
456
|
+
randomPacking = cleanedWord | val << offset;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function getRandomPacked(uint256 size, uint256 offset) public view returns (uint256) {
|
|
460
|
+
// Generate mask based on the size of the value
|
|
461
|
+
uint256 mask = _getMask(size);
|
|
462
|
+
// Shift to place the bits in the correct position, and use mask to zero out remaining bits
|
|
463
|
+
return (randomPacking >> offset) & mask;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function getRandomPacked(uint8 shifts, uint8[] memory shiftSizes, uint8 elem) public view returns (uint256) {
|
|
467
|
+
require(elem < shifts, "!elem");
|
|
468
|
+
uint256 leftBits;
|
|
469
|
+
uint256 rightBits;
|
|
470
|
+
|
|
471
|
+
for (uint256 i; i < shiftSizes.length; i++) {
|
|
472
|
+
if (i < elem) {
|
|
473
|
+
leftBits += shiftSizes[i];
|
|
474
|
+
} else if (elem != i) {
|
|
475
|
+
rightBits += shiftSizes[i];
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// we may have some right bits unaccounted for
|
|
480
|
+
leftBits += 256 - (leftBits + shiftSizes[elem] + rightBits);
|
|
481
|
+
|
|
482
|
+
// clear left bits, then clear right bits and realign
|
|
483
|
+
return (randomPacking << leftBits) >> (leftBits + rightBits);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
2
|
+
pragma solidity >=0.8.13 <0.9.0;
|
|
3
|
+
|
|
4
|
+
import {Test, console2, StdStyle} from "../src/Test.sol";
|
|
5
|
+
|
|
6
|
+
contract StdStyleTest is Test {
|
|
7
|
+
function test_StyleColor() public pure {
|
|
8
|
+
console2.log(StdStyle.red("StdStyle.red String Test"));
|
|
9
|
+
console2.log(StdStyle.red(uint256(10e18)));
|
|
10
|
+
console2.log(StdStyle.red(int256(-10e18)));
|
|
11
|
+
console2.log(StdStyle.red(true));
|
|
12
|
+
console2.log(StdStyle.red(address(0)));
|
|
13
|
+
console2.log(StdStyle.redBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
14
|
+
console2.log(StdStyle.redBytes32("StdStyle.redBytes32"));
|
|
15
|
+
console2.log(StdStyle.green("StdStyle.green String Test"));
|
|
16
|
+
console2.log(StdStyle.green(uint256(10e18)));
|
|
17
|
+
console2.log(StdStyle.green(int256(-10e18)));
|
|
18
|
+
console2.log(StdStyle.green(true));
|
|
19
|
+
console2.log(StdStyle.green(address(0)));
|
|
20
|
+
console2.log(StdStyle.greenBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
21
|
+
console2.log(StdStyle.greenBytes32("StdStyle.greenBytes32"));
|
|
22
|
+
console2.log(StdStyle.yellow("StdStyle.yellow String Test"));
|
|
23
|
+
console2.log(StdStyle.yellow(uint256(10e18)));
|
|
24
|
+
console2.log(StdStyle.yellow(int256(-10e18)));
|
|
25
|
+
console2.log(StdStyle.yellow(true));
|
|
26
|
+
console2.log(StdStyle.yellow(address(0)));
|
|
27
|
+
console2.log(StdStyle.yellowBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
28
|
+
console2.log(StdStyle.yellowBytes32("StdStyle.yellowBytes32"));
|
|
29
|
+
console2.log(StdStyle.blue("StdStyle.blue String Test"));
|
|
30
|
+
console2.log(StdStyle.blue(uint256(10e18)));
|
|
31
|
+
console2.log(StdStyle.blue(int256(-10e18)));
|
|
32
|
+
console2.log(StdStyle.blue(true));
|
|
33
|
+
console2.log(StdStyle.blue(address(0)));
|
|
34
|
+
console2.log(StdStyle.blueBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
35
|
+
console2.log(StdStyle.blueBytes32("StdStyle.blueBytes32"));
|
|
36
|
+
console2.log(StdStyle.magenta("StdStyle.magenta String Test"));
|
|
37
|
+
console2.log(StdStyle.magenta(uint256(10e18)));
|
|
38
|
+
console2.log(StdStyle.magenta(int256(-10e18)));
|
|
39
|
+
console2.log(StdStyle.magenta(true));
|
|
40
|
+
console2.log(StdStyle.magenta(address(0)));
|
|
41
|
+
console2.log(StdStyle.magentaBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
42
|
+
console2.log(StdStyle.magentaBytes32("StdStyle.magentaBytes32"));
|
|
43
|
+
console2.log(StdStyle.cyan("StdStyle.cyan String Test"));
|
|
44
|
+
console2.log(StdStyle.cyan(uint256(10e18)));
|
|
45
|
+
console2.log(StdStyle.cyan(int256(-10e18)));
|
|
46
|
+
console2.log(StdStyle.cyan(true));
|
|
47
|
+
console2.log(StdStyle.cyan(address(0)));
|
|
48
|
+
console2.log(StdStyle.cyanBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
49
|
+
console2.log(StdStyle.cyanBytes32("StdStyle.cyanBytes32"));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function test_StyleFontWeight() public pure {
|
|
53
|
+
console2.log(StdStyle.bold("StdStyle.bold String Test"));
|
|
54
|
+
console2.log(StdStyle.bold(uint256(10e18)));
|
|
55
|
+
console2.log(StdStyle.bold(int256(-10e18)));
|
|
56
|
+
console2.log(StdStyle.bold(address(0)));
|
|
57
|
+
console2.log(StdStyle.bold(true));
|
|
58
|
+
console2.log(StdStyle.boldBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
59
|
+
console2.log(StdStyle.boldBytes32("StdStyle.boldBytes32"));
|
|
60
|
+
console2.log(StdStyle.dim("StdStyle.dim String Test"));
|
|
61
|
+
console2.log(StdStyle.dim(uint256(10e18)));
|
|
62
|
+
console2.log(StdStyle.dim(int256(-10e18)));
|
|
63
|
+
console2.log(StdStyle.dim(address(0)));
|
|
64
|
+
console2.log(StdStyle.dim(true));
|
|
65
|
+
console2.log(StdStyle.dimBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
66
|
+
console2.log(StdStyle.dimBytes32("StdStyle.dimBytes32"));
|
|
67
|
+
console2.log(StdStyle.italic("StdStyle.italic String Test"));
|
|
68
|
+
console2.log(StdStyle.italic(uint256(10e18)));
|
|
69
|
+
console2.log(StdStyle.italic(int256(-10e18)));
|
|
70
|
+
console2.log(StdStyle.italic(address(0)));
|
|
71
|
+
console2.log(StdStyle.italic(true));
|
|
72
|
+
console2.log(StdStyle.italicBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
73
|
+
console2.log(StdStyle.italicBytes32("StdStyle.italicBytes32"));
|
|
74
|
+
console2.log(StdStyle.underline("StdStyle.underline String Test"));
|
|
75
|
+
console2.log(StdStyle.underline(uint256(10e18)));
|
|
76
|
+
console2.log(StdStyle.underline(int256(-10e18)));
|
|
77
|
+
console2.log(StdStyle.underline(address(0)));
|
|
78
|
+
console2.log(StdStyle.underline(true));
|
|
79
|
+
console2.log(StdStyle.underlineBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
80
|
+
console2.log(StdStyle.underlineBytes32("StdStyle.underlineBytes32"));
|
|
81
|
+
console2.log(StdStyle.inverse("StdStyle.inverse String Test"));
|
|
82
|
+
console2.log(StdStyle.inverse(uint256(10e18)));
|
|
83
|
+
console2.log(StdStyle.inverse(int256(-10e18)));
|
|
84
|
+
console2.log(StdStyle.inverse(address(0)));
|
|
85
|
+
console2.log(StdStyle.inverse(true));
|
|
86
|
+
console2.log(StdStyle.inverseBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
|
|
87
|
+
console2.log(StdStyle.inverseBytes32("StdStyle.inverseBytes32"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function test_StyleCombined() public pure {
|
|
91
|
+
console2.log(StdStyle.red(StdStyle.bold("Red Bold String Test")));
|
|
92
|
+
console2.log(StdStyle.green(StdStyle.dim(uint256(10e18))));
|
|
93
|
+
console2.log(StdStyle.yellow(StdStyle.italic(int256(-10e18))));
|
|
94
|
+
console2.log(StdStyle.blue(StdStyle.underline(address(0))));
|
|
95
|
+
console2.log(StdStyle.magenta(StdStyle.inverse(true)));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function test_StyleCustom() public pure {
|
|
99
|
+
console2.log(h1("Custom Style 1"));
|
|
100
|
+
console2.log(h2("Custom Style 2"));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function h1(string memory a) private pure returns (string memory) {
|
|
104
|
+
return StdStyle.cyan(StdStyle.inverse(StdStyle.bold(a)));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function h2(string memory a) private pure returns (string memory) {
|
|
108
|
+
return StdStyle.magenta(StdStyle.bold(StdStyle.underline(a)));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
2
|
+
pragma solidity >=0.8.13 <0.9.0;
|
|
3
|
+
|
|
4
|
+
import {Test, stdToml} from "../src/Test.sol";
|
|
5
|
+
|
|
6
|
+
contract StdTomlTest is Test {
|
|
7
|
+
using stdToml for string;
|
|
8
|
+
|
|
9
|
+
string root;
|
|
10
|
+
string path;
|
|
11
|
+
|
|
12
|
+
function setUp() public {
|
|
13
|
+
root = vm.projectRoot();
|
|
14
|
+
path = string.concat(root, "/test/fixtures/test.toml");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
struct SimpleToml {
|
|
18
|
+
uint256 a;
|
|
19
|
+
string b;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
struct NestedToml {
|
|
23
|
+
uint256 a;
|
|
24
|
+
string b;
|
|
25
|
+
SimpleToml c;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function test_readToml() public view {
|
|
29
|
+
string memory json = vm.readFile(path);
|
|
30
|
+
assertEq(json.readUint(".a"), 123);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function test_writeToml() public {
|
|
34
|
+
string memory json = "json";
|
|
35
|
+
json.serialize("a", uint256(123));
|
|
36
|
+
string memory semiFinal = json.serialize("b", string("test"));
|
|
37
|
+
string memory finalJson = json.serialize("c", semiFinal);
|
|
38
|
+
finalJson.write(path);
|
|
39
|
+
|
|
40
|
+
string memory toml = vm.readFile(path);
|
|
41
|
+
bytes memory data = toml.parseRaw("$");
|
|
42
|
+
NestedToml memory decodedData = abi.decode(data, (NestedToml));
|
|
43
|
+
|
|
44
|
+
assertEq(decodedData.a, 123);
|
|
45
|
+
assertEq(decodedData.b, "test");
|
|
46
|
+
assertEq(decodedData.c.a, 123);
|
|
47
|
+
assertEq(decodedData.c.b, "test");
|
|
48
|
+
}
|
|
49
|
+
}
|