@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,452 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.13;
|
|
3
|
+
|
|
4
|
+
import {Test} from "../src/Test.sol";
|
|
5
|
+
import {Variable, Type, TypeKind, LibVariable} from "../src/LibVariable.sol";
|
|
6
|
+
|
|
7
|
+
contract LibVariableTest is Test {
|
|
8
|
+
using LibVariable for Type;
|
|
9
|
+
using LibVariable for TypeKind;
|
|
10
|
+
|
|
11
|
+
LibVariableHelper internal helper;
|
|
12
|
+
|
|
13
|
+
bytes internal expectedErr;
|
|
14
|
+
Variable internal uninitVar;
|
|
15
|
+
Variable internal boolVar;
|
|
16
|
+
Variable internal addressVar;
|
|
17
|
+
Variable internal bytes32Var;
|
|
18
|
+
Variable internal uintVar;
|
|
19
|
+
Variable internal intVar;
|
|
20
|
+
Variable internal stringVar;
|
|
21
|
+
Variable internal bytesVar;
|
|
22
|
+
Variable internal boolArrayVar;
|
|
23
|
+
Variable internal addressArrayVar;
|
|
24
|
+
Variable internal bytes32ArrayVar;
|
|
25
|
+
Variable internal uintArrayVar;
|
|
26
|
+
Variable internal intArrayVar;
|
|
27
|
+
Variable internal stringArrayVar;
|
|
28
|
+
Variable internal bytesArrayVar;
|
|
29
|
+
|
|
30
|
+
function setUp() public {
|
|
31
|
+
helper = new LibVariableHelper();
|
|
32
|
+
|
|
33
|
+
// UNINITIALIZED
|
|
34
|
+
uninitVar = Variable(Type(TypeKind.None, false), "");
|
|
35
|
+
|
|
36
|
+
// SINGLE VALUES
|
|
37
|
+
boolVar = Variable(Type(TypeKind.Bool, false), abi.encode(true));
|
|
38
|
+
addressVar = Variable(Type(TypeKind.Address, false), abi.encode(address(0xdeadbeef)));
|
|
39
|
+
bytes32Var = Variable(Type(TypeKind.Bytes32, false), abi.encode(bytes32(uint256(42))));
|
|
40
|
+
uintVar = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(123)));
|
|
41
|
+
intVar = Variable(Type(TypeKind.Int256, false), abi.encode(int256(-123)));
|
|
42
|
+
stringVar = Variable(Type(TypeKind.String, false), abi.encode("hello world"));
|
|
43
|
+
bytesVar = Variable(Type(TypeKind.Bytes, false), abi.encode(hex"c0ffee"));
|
|
44
|
+
|
|
45
|
+
// ARRAY VALUES
|
|
46
|
+
bool[] memory bools = new bool[](2);
|
|
47
|
+
bools[0] = true;
|
|
48
|
+
bools[1] = false;
|
|
49
|
+
boolArrayVar = Variable(Type(TypeKind.Bool, true), abi.encode(bools));
|
|
50
|
+
|
|
51
|
+
address[] memory addrs = new address[](2);
|
|
52
|
+
addrs[0] = address(0x1);
|
|
53
|
+
addrs[1] = address(0x2);
|
|
54
|
+
addressArrayVar = Variable(Type(TypeKind.Address, true), abi.encode(addrs));
|
|
55
|
+
|
|
56
|
+
bytes32[] memory b32s = new bytes32[](2);
|
|
57
|
+
b32s[0] = bytes32(uint256(1));
|
|
58
|
+
b32s[1] = bytes32(uint256(2));
|
|
59
|
+
bytes32ArrayVar = Variable(Type(TypeKind.Bytes32, true), abi.encode(b32s));
|
|
60
|
+
|
|
61
|
+
uint256[] memory uints = new uint256[](2);
|
|
62
|
+
uints[0] = 1;
|
|
63
|
+
uints[1] = 2;
|
|
64
|
+
uintArrayVar = Variable(Type(TypeKind.Uint256, true), abi.encode(uints));
|
|
65
|
+
|
|
66
|
+
int256[] memory ints = new int256[](2);
|
|
67
|
+
ints[0] = -1;
|
|
68
|
+
ints[1] = 2;
|
|
69
|
+
intArrayVar = Variable(Type(TypeKind.Int256, true), abi.encode(ints));
|
|
70
|
+
|
|
71
|
+
string[] memory strings = new string[](2);
|
|
72
|
+
strings[0] = "one";
|
|
73
|
+
strings[1] = "two";
|
|
74
|
+
stringArrayVar = Variable(Type(TypeKind.String, true), abi.encode(strings));
|
|
75
|
+
|
|
76
|
+
bytes[] memory b = new bytes[](2);
|
|
77
|
+
b[0] = hex"01";
|
|
78
|
+
b[1] = hex"02";
|
|
79
|
+
bytesArrayVar = Variable(Type(TypeKind.Bytes, true), abi.encode(b));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// -- SUCCESS CASES --------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
function test_TypeHelpers() public view {
|
|
85
|
+
// TypeKind.toString()
|
|
86
|
+
assertEq(TypeKind.None.toString(), "none");
|
|
87
|
+
assertEq(TypeKind.Bool.toString(), "bool");
|
|
88
|
+
assertEq(TypeKind.Address.toString(), "address");
|
|
89
|
+
assertEq(TypeKind.Bytes32.toString(), "bytes32");
|
|
90
|
+
assertEq(TypeKind.Uint256.toString(), "uint256");
|
|
91
|
+
assertEq(TypeKind.Int256.toString(), "int256");
|
|
92
|
+
assertEq(TypeKind.String.toString(), "string");
|
|
93
|
+
assertEq(TypeKind.Bytes.toString(), "bytes");
|
|
94
|
+
|
|
95
|
+
// TypeKind.toTomlKey()
|
|
96
|
+
assertEq(TypeKind.Uint256.toTomlKey(), "uint");
|
|
97
|
+
assertEq(TypeKind.Int256.toTomlKey(), "int");
|
|
98
|
+
assertEq(TypeKind.Bytes32.toTomlKey(), "bytes32");
|
|
99
|
+
|
|
100
|
+
// Type.toString()
|
|
101
|
+
assertEq(boolVar.ty.toString(), "bool");
|
|
102
|
+
assertEq(boolArrayVar.ty.toString(), "bool[]");
|
|
103
|
+
assertEq(uintVar.ty.toString(), "uint256");
|
|
104
|
+
assertEq(uintArrayVar.ty.toString(), "uint256[]");
|
|
105
|
+
assertEq(uninitVar.ty.toString(), "none");
|
|
106
|
+
|
|
107
|
+
// Type.isEqual()
|
|
108
|
+
assertTrue(boolVar.ty.isEqual(Type(TypeKind.Bool, false)));
|
|
109
|
+
assertFalse(boolVar.ty.isEqual(Type(TypeKind.Bool, true)));
|
|
110
|
+
assertFalse(boolVar.ty.isEqual(Type(TypeKind.Address, false)));
|
|
111
|
+
|
|
112
|
+
// Type.assertEq()
|
|
113
|
+
boolVar.ty.assertEq(Type(TypeKind.Bool, false));
|
|
114
|
+
uintArrayVar.ty.assertEq(Type(TypeKind.Uint256, true));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function test_Coercion() public view {
|
|
118
|
+
// Single values
|
|
119
|
+
assertTrue(helper.toBool(boolVar));
|
|
120
|
+
assertEq(helper.toAddress(addressVar), address(0xdeadbeef));
|
|
121
|
+
assertEq(helper.toBytes32(bytes32Var), bytes32(uint256(42)));
|
|
122
|
+
assertEq(helper.toUint256(uintVar), 123);
|
|
123
|
+
assertEq(helper.toInt256(intVar), -123);
|
|
124
|
+
assertEq(helper.toString(stringVar), "hello world");
|
|
125
|
+
assertEq(helper.toBytes(bytesVar), hex"c0ffee");
|
|
126
|
+
|
|
127
|
+
// Bool array
|
|
128
|
+
bool[] memory bools = helper.toBoolArray(boolArrayVar);
|
|
129
|
+
assertEq(bools.length, 2);
|
|
130
|
+
assertTrue(bools[0]);
|
|
131
|
+
assertFalse(bools[1]);
|
|
132
|
+
|
|
133
|
+
// Address array
|
|
134
|
+
address[] memory addrs = helper.toAddressArray(addressArrayVar);
|
|
135
|
+
assertEq(addrs.length, 2);
|
|
136
|
+
assertEq(addrs[0], address(0x1));
|
|
137
|
+
assertEq(addrs[1], address(0x2));
|
|
138
|
+
|
|
139
|
+
// String array
|
|
140
|
+
string[] memory strings = helper.toStringArray(stringArrayVar);
|
|
141
|
+
assertEq(strings.length, 2);
|
|
142
|
+
assertEq(strings[0], "one");
|
|
143
|
+
assertEq(strings[1], "two");
|
|
144
|
+
|
|
145
|
+
// Bytes32 array
|
|
146
|
+
bytes32[] memory b32s = helper.toBytes32Array(bytes32ArrayVar);
|
|
147
|
+
assertEq(b32s.length, 2);
|
|
148
|
+
assertEq(b32s[0], bytes32(uint256(1)));
|
|
149
|
+
assertEq(b32s[1], bytes32(uint256(2)));
|
|
150
|
+
|
|
151
|
+
// Int array
|
|
152
|
+
int256[] memory ints = helper.toInt256Array(intArrayVar);
|
|
153
|
+
assertEq(ints.length, 2);
|
|
154
|
+
assertEq(ints[0], -1);
|
|
155
|
+
assertEq(ints[1], 2);
|
|
156
|
+
|
|
157
|
+
// Bytes array
|
|
158
|
+
bytes[] memory b = helper.toBytesArray(bytesArrayVar);
|
|
159
|
+
assertEq(b.length, 2);
|
|
160
|
+
assertEq(b[0], hex"01");
|
|
161
|
+
assertEq(b[1], hex"02");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function test_Downcasting() public view {
|
|
165
|
+
// Uint downcasting
|
|
166
|
+
Variable memory v_uint_small = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(100)));
|
|
167
|
+
assertEq(helper.toUint128(v_uint_small), 100);
|
|
168
|
+
assertEq(helper.toUint64(v_uint_small), 100);
|
|
169
|
+
assertEq(helper.toUint32(v_uint_small), 100);
|
|
170
|
+
assertEq(helper.toUint16(v_uint_small), 100);
|
|
171
|
+
assertEq(helper.toUint8(v_uint_small), 100);
|
|
172
|
+
|
|
173
|
+
// Uint array downcasting
|
|
174
|
+
uint256[] memory small_uints = new uint256[](2);
|
|
175
|
+
small_uints[0] = 10;
|
|
176
|
+
small_uints[1] = 20;
|
|
177
|
+
Variable memory v_uint_array_small = Variable(Type(TypeKind.Uint256, true), abi.encode(small_uints));
|
|
178
|
+
uint8[] memory u8_array = helper.toUint8Array(v_uint_array_small);
|
|
179
|
+
assertEq(u8_array[0], 10);
|
|
180
|
+
assertEq(u8_array[1], 20);
|
|
181
|
+
|
|
182
|
+
// Int downcasting
|
|
183
|
+
Variable memory v_int_small_pos = Variable(Type(TypeKind.Int256, false), abi.encode(int256(100)));
|
|
184
|
+
Variable memory v_int_small_neg = Variable(Type(TypeKind.Int256, false), abi.encode(int256(-100)));
|
|
185
|
+
assertEq(helper.toInt128(v_int_small_pos), 100);
|
|
186
|
+
assertEq(helper.toInt64(v_int_small_neg), -100);
|
|
187
|
+
assertEq(helper.toInt32(v_int_small_pos), 100);
|
|
188
|
+
assertEq(helper.toInt16(v_int_small_neg), -100);
|
|
189
|
+
assertEq(helper.toInt8(v_int_small_pos), 100);
|
|
190
|
+
|
|
191
|
+
// Int array downcasting
|
|
192
|
+
int256[] memory small_ints = new int256[](2);
|
|
193
|
+
small_ints[0] = -10;
|
|
194
|
+
small_ints[1] = 20;
|
|
195
|
+
Variable memory intArraySmall = Variable(Type(TypeKind.Int256, true), abi.encode(small_ints));
|
|
196
|
+
int8[] memory i8_array = helper.toInt8Array(intArraySmall);
|
|
197
|
+
assertEq(i8_array[0], -10);
|
|
198
|
+
assertEq(i8_array[1], 20);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// -- REVERT CASES ---------------------------------------------------------
|
|
202
|
+
|
|
203
|
+
function testRevert_NotInitialized() public {
|
|
204
|
+
vm.expectRevert(LibVariable.NotInitialized.selector);
|
|
205
|
+
helper.toBool(uninitVar);
|
|
206
|
+
|
|
207
|
+
vm.expectRevert(LibVariable.NotInitialized.selector);
|
|
208
|
+
helper.toAddressArray(uninitVar);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function testRevert_assertExists() public {
|
|
212
|
+
vm.expectRevert(LibVariable.NotInitialized.selector);
|
|
213
|
+
helper.assertExists(uninitVar);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function testRevert_TypeMismatch() public {
|
|
217
|
+
// Single values
|
|
218
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256", "bool"));
|
|
219
|
+
helper.toUint256(boolVar);
|
|
220
|
+
|
|
221
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "address", "string"));
|
|
222
|
+
helper.toAddress(stringVar);
|
|
223
|
+
|
|
224
|
+
// Arrays
|
|
225
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256[]", "bool[]"));
|
|
226
|
+
helper.toUint256Array(boolArrayVar);
|
|
227
|
+
|
|
228
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "address[]", "string[]"));
|
|
229
|
+
helper.toAddressArray(stringArrayVar);
|
|
230
|
+
|
|
231
|
+
// Single value to array
|
|
232
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "bool[]", "bool"));
|
|
233
|
+
helper.toBoolArray(boolVar);
|
|
234
|
+
|
|
235
|
+
// Array to single value
|
|
236
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "bool", "bool[]"));
|
|
237
|
+
helper.toBool(boolArrayVar);
|
|
238
|
+
|
|
239
|
+
// assertEq reverts
|
|
240
|
+
vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256", "bool"));
|
|
241
|
+
helper.assertEq(boolVar.ty, Type(TypeKind.Uint256, false));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function testRevert_UnsafeCast() public {
|
|
245
|
+
// uint overflow
|
|
246
|
+
Variable memory uintLarge = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(type(uint128).max) + 1));
|
|
247
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'uint128'");
|
|
248
|
+
vm.expectRevert(expectedErr);
|
|
249
|
+
helper.toUint128(uintLarge);
|
|
250
|
+
|
|
251
|
+
// int overflow
|
|
252
|
+
Variable memory intLarge = Variable(Type(TypeKind.Int256, false), abi.encode(int256(type(int128).max) + 1));
|
|
253
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'int128'");
|
|
254
|
+
|
|
255
|
+
vm.expectRevert(expectedErr);
|
|
256
|
+
helper.toInt128(intLarge);
|
|
257
|
+
|
|
258
|
+
// int underflow
|
|
259
|
+
Variable memory intSmall = Variable(Type(TypeKind.Int256, false), abi.encode(int256(type(int128).min) - 1));
|
|
260
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'int128'");
|
|
261
|
+
|
|
262
|
+
vm.expectRevert(expectedErr);
|
|
263
|
+
helper.toInt128(intSmall);
|
|
264
|
+
|
|
265
|
+
// uint array overflow
|
|
266
|
+
uint256[] memory uintArray = new uint256[](2);
|
|
267
|
+
uintArray[0] = 10;
|
|
268
|
+
uintArray[1] = uint256(type(uint64).max) + 1;
|
|
269
|
+
Variable memory uintArrayLarge = Variable(Type(TypeKind.Uint256, true), abi.encode(uintArray));
|
|
270
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'uint64'");
|
|
271
|
+
|
|
272
|
+
vm.expectRevert(expectedErr);
|
|
273
|
+
helper.toUint64Array(uintArrayLarge);
|
|
274
|
+
|
|
275
|
+
// int array overflow
|
|
276
|
+
int256[] memory intArray = new int256[](2);
|
|
277
|
+
intArray[0] = 10;
|
|
278
|
+
intArray[1] = int256(type(int64).max) + 1;
|
|
279
|
+
Variable memory intArrayLarge = Variable(Type(TypeKind.Int256, true), abi.encode(intArray));
|
|
280
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'int64'");
|
|
281
|
+
|
|
282
|
+
vm.expectRevert(expectedErr);
|
|
283
|
+
helper.toInt64Array(intArrayLarge);
|
|
284
|
+
|
|
285
|
+
// int array underflow
|
|
286
|
+
intArray[0] = 10;
|
|
287
|
+
intArray[1] = int256(type(int64).min) - 1;
|
|
288
|
+
Variable memory intArraySmall = Variable(Type(TypeKind.Int256, true), abi.encode(intArray));
|
|
289
|
+
expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'int64'");
|
|
290
|
+
|
|
291
|
+
vm.expectRevert(expectedErr);
|
|
292
|
+
helper.toInt64Array(intArraySmall);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/// @dev We must use an external helper contract to ensure proper call depth for `vm.expectRevert`,
|
|
297
|
+
/// as direct library calls are inlined by the compiler, causing call depth issues.
|
|
298
|
+
contract LibVariableHelper {
|
|
299
|
+
using LibVariable for Type;
|
|
300
|
+
using LibVariable for TypeKind;
|
|
301
|
+
|
|
302
|
+
// Assertions
|
|
303
|
+
function assertExists(Variable memory v) external pure {
|
|
304
|
+
v.assertExists();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function assertEq(Type memory t1, Type memory t2) external pure {
|
|
308
|
+
t1.assertEq(t2);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Single Value Coercion
|
|
312
|
+
function toBool(Variable memory v) external pure returns (bool) {
|
|
313
|
+
return v.toBool();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function toAddress(Variable memory v) external pure returns (address) {
|
|
317
|
+
return v.toAddress();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function toBytes32(Variable memory v) external pure returns (bytes32) {
|
|
321
|
+
return v.toBytes32();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function toUint256(Variable memory v) external pure returns (uint256) {
|
|
325
|
+
return v.toUint256();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function toInt256(Variable memory v) external pure returns (int256) {
|
|
329
|
+
return v.toInt256();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function toString(Variable memory v) external pure returns (string memory) {
|
|
333
|
+
return v.toString();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function toBytes(Variable memory v) external pure returns (bytes memory) {
|
|
337
|
+
return v.toBytes();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Array Coercion
|
|
341
|
+
function toBoolArray(Variable memory v) external pure returns (bool[] memory) {
|
|
342
|
+
return v.toBoolArray();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function toAddressArray(Variable memory v) external pure returns (address[] memory) {
|
|
346
|
+
return v.toAddressArray();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function toBytes32Array(Variable memory v) external pure returns (bytes32[] memory) {
|
|
350
|
+
return v.toBytes32Array();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function toUint256Array(Variable memory v) external pure returns (uint256[] memory) {
|
|
354
|
+
return v.toUint256Array();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function toInt256Array(Variable memory v) external pure returns (int256[] memory) {
|
|
358
|
+
return v.toInt256Array();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function toStringArray(Variable memory v) external pure returns (string[] memory) {
|
|
362
|
+
return v.toStringArray();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function toBytesArray(Variable memory v) external pure returns (bytes[] memory) {
|
|
366
|
+
return v.toBytesArray();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Uint Downcasting
|
|
370
|
+
function toUint128(Variable memory v) external pure returns (uint128) {
|
|
371
|
+
return v.toUint128();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function toUint64(Variable memory v) external pure returns (uint64) {
|
|
375
|
+
return v.toUint64();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function toUint32(Variable memory v) external pure returns (uint32) {
|
|
379
|
+
return v.toUint32();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function toUint16(Variable memory v) external pure returns (uint16) {
|
|
383
|
+
return v.toUint16();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function toUint8(Variable memory v) external pure returns (uint8) {
|
|
387
|
+
return v.toUint8();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Int Downcasting
|
|
391
|
+
function toInt128(Variable memory v) external pure returns (int128) {
|
|
392
|
+
return v.toInt128();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function toInt64(Variable memory v) external pure returns (int64) {
|
|
396
|
+
return v.toInt64();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function toInt32(Variable memory v) external pure returns (int32) {
|
|
400
|
+
return v.toInt32();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function toInt16(Variable memory v) external pure returns (int16) {
|
|
404
|
+
return v.toInt16();
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function toInt8(Variable memory v) external pure returns (int8) {
|
|
408
|
+
return v.toInt8();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Uint Array Downcasting
|
|
412
|
+
function toUint128Array(Variable memory v) external pure returns (uint128[] memory) {
|
|
413
|
+
return v.toUint128Array();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function toUint64Array(Variable memory v) external pure returns (uint64[] memory) {
|
|
417
|
+
return v.toUint64Array();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function toUint32Array(Variable memory v) external pure returns (uint32[] memory) {
|
|
421
|
+
return v.toUint32Array();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function toUint16Array(Variable memory v) external pure returns (uint16[] memory) {
|
|
425
|
+
return v.toUint16Array();
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function toUint8Array(Variable memory v) external pure returns (uint8[] memory) {
|
|
429
|
+
return v.toUint8Array();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Int Array Downcasting
|
|
433
|
+
function toInt128Array(Variable memory v) external pure returns (int128[] memory) {
|
|
434
|
+
return v.toInt128Array();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function toInt64Array(Variable memory v) external pure returns (int64[] memory) {
|
|
438
|
+
return v.toInt64Array();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function toInt32Array(Variable memory v) external pure returns (int32[] memory) {
|
|
442
|
+
return v.toInt32Array();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function toInt16Array(Variable memory v) external pure returns (int16[] memory) {
|
|
446
|
+
return v.toInt16Array();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function toInt8Array(Variable memory v) external pure returns (int8[] memory) {
|
|
450
|
+
return v.toInt8Array();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
2
|
+
pragma solidity >=0.8.13 <0.9.0;
|
|
3
|
+
|
|
4
|
+
import {StdAssertions} from "../src/StdAssertions.sol";
|
|
5
|
+
import {Vm} from "../src/Vm.sol";
|
|
6
|
+
|
|
7
|
+
interface VmInternal is Vm {
|
|
8
|
+
function _expectCheatcodeRevert(bytes memory message) external;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
contract StdAssertionsTest is StdAssertions {
|
|
12
|
+
string constant errorMessage = "User provided message";
|
|
13
|
+
uint256 constant maxDecimals = 77;
|
|
14
|
+
|
|
15
|
+
bool constant SHOULD_REVERT = true;
|
|
16
|
+
bool constant SHOULD_RETURN = false;
|
|
17
|
+
|
|
18
|
+
bool constant STRICT_REVERT_DATA = true;
|
|
19
|
+
bool constant NON_STRICT_REVERT_DATA = false;
|
|
20
|
+
|
|
21
|
+
VmInternal constant vm = VmInternal(address(uint160(uint256(keccak256("hevm cheat code")))));
|
|
22
|
+
|
|
23
|
+
function testFuzz_AssertEqCall_Return_Pass(
|
|
24
|
+
bytes memory callDataA,
|
|
25
|
+
bytes memory callDataB,
|
|
26
|
+
bytes memory returnData,
|
|
27
|
+
bool strictRevertData
|
|
28
|
+
) external {
|
|
29
|
+
address targetA = address(new TestMockCall(returnData, SHOULD_RETURN));
|
|
30
|
+
address targetB = address(new TestMockCall(returnData, SHOULD_RETURN));
|
|
31
|
+
|
|
32
|
+
assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function testFuzz_RevertWhenCalled_AssertEqCall_Return_Fail(
|
|
36
|
+
bytes memory callDataA,
|
|
37
|
+
bytes memory callDataB,
|
|
38
|
+
bytes memory returnDataA,
|
|
39
|
+
bytes memory returnDataB,
|
|
40
|
+
bool strictRevertData
|
|
41
|
+
) external {
|
|
42
|
+
vm.assume(keccak256(returnDataA) != keccak256(returnDataB));
|
|
43
|
+
|
|
44
|
+
address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
|
|
45
|
+
address targetB = address(new TestMockCall(returnDataB, SHOULD_RETURN));
|
|
46
|
+
|
|
47
|
+
vm._expectCheatcodeRevert(
|
|
48
|
+
bytes(
|
|
49
|
+
string.concat(
|
|
50
|
+
"Call return data does not match: ", vm.toString(returnDataA), " != ", vm.toString(returnDataB)
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function testFuzz_AssertEqCall_Revert_Pass(
|
|
58
|
+
bytes memory callDataA,
|
|
59
|
+
bytes memory callDataB,
|
|
60
|
+
bytes memory revertDataA,
|
|
61
|
+
bytes memory revertDataB
|
|
62
|
+
) external {
|
|
63
|
+
address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
|
|
64
|
+
address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
|
|
65
|
+
|
|
66
|
+
assertEqCall(targetA, callDataA, targetB, callDataB, NON_STRICT_REVERT_DATA);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function testFuzz_RevertWhenCalled_AssertEqCall_Revert_Fail(
|
|
70
|
+
bytes memory callDataA,
|
|
71
|
+
bytes memory callDataB,
|
|
72
|
+
bytes memory revertDataA,
|
|
73
|
+
bytes memory revertDataB
|
|
74
|
+
) external {
|
|
75
|
+
vm.assume(keccak256(revertDataA) != keccak256(revertDataB));
|
|
76
|
+
|
|
77
|
+
address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
|
|
78
|
+
address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
|
|
79
|
+
|
|
80
|
+
vm._expectCheatcodeRevert(
|
|
81
|
+
bytes(
|
|
82
|
+
string.concat(
|
|
83
|
+
"Call revert data does not match: ", vm.toString(revertDataA), " != ", vm.toString(revertDataB)
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
assertEqCall(targetA, callDataA, targetB, callDataB, STRICT_REVERT_DATA);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function testFuzz_RevertWhenCalled_AssertEqCall_Fail(
|
|
91
|
+
bytes memory callDataA,
|
|
92
|
+
bytes memory callDataB,
|
|
93
|
+
bytes memory returnDataA,
|
|
94
|
+
bytes memory returnDataB,
|
|
95
|
+
bool strictRevertData
|
|
96
|
+
) external {
|
|
97
|
+
address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
|
|
98
|
+
address targetB = address(new TestMockCall(returnDataB, SHOULD_REVERT));
|
|
99
|
+
|
|
100
|
+
vm.expectRevert(bytes("assertion failed"));
|
|
101
|
+
this.assertEqCallExternal(targetA, callDataA, targetB, callDataB, strictRevertData);
|
|
102
|
+
|
|
103
|
+
vm.expectRevert(bytes("assertion failed"));
|
|
104
|
+
this.assertEqCallExternal(targetB, callDataB, targetA, callDataA, strictRevertData);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Helper function to test outcome of assertEqCall via `expect` cheatcodes
|
|
108
|
+
function assertEqCallExternal(
|
|
109
|
+
address targetA,
|
|
110
|
+
bytes memory callDataA,
|
|
111
|
+
address targetB,
|
|
112
|
+
bytes memory callDataB,
|
|
113
|
+
bool strictRevertData
|
|
114
|
+
) public {
|
|
115
|
+
assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
contract TestMockCall {
|
|
120
|
+
bytes returnData;
|
|
121
|
+
bool shouldRevert;
|
|
122
|
+
|
|
123
|
+
constructor(bytes memory returnData_, bool shouldRevert_) {
|
|
124
|
+
returnData = returnData_;
|
|
125
|
+
shouldRevert = shouldRevert_;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fallback() external payable {
|
|
129
|
+
bytes memory returnData_ = returnData;
|
|
130
|
+
|
|
131
|
+
if (shouldRevert) {
|
|
132
|
+
assembly {
|
|
133
|
+
revert(add(returnData_, 0x20), mload(returnData_))
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
assembly {
|
|
137
|
+
return(add(returnData_, 0x20), mload(returnData_))
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|