@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.
Files changed (81) hide show
  1. package/.devcontainer/Dockerfile +117 -0
  2. package/.devcontainer/devcontainer.json +62 -0
  3. package/.devcontainer/init-firewall.sh +118 -0
  4. package/.github/workflows/test.yml +38 -0
  5. package/.gitmodules +3 -0
  6. package/CLAUDE.md +39 -0
  7. package/README.md +33 -0
  8. package/foundry.lock +8 -0
  9. package/foundry.toml +6 -0
  10. package/index.ts +97 -0
  11. package/lib/forge-std/.gitattributes +1 -0
  12. package/lib/forge-std/.github/CODEOWNERS +1 -0
  13. package/lib/forge-std/.github/dependabot.yml +6 -0
  14. package/lib/forge-std/.github/workflows/ci.yml +125 -0
  15. package/lib/forge-std/.github/workflows/sync.yml +36 -0
  16. package/lib/forge-std/CONTRIBUTING.md +193 -0
  17. package/lib/forge-std/LICENSE-APACHE +203 -0
  18. package/lib/forge-std/LICENSE-MIT +25 -0
  19. package/lib/forge-std/README.md +314 -0
  20. package/lib/forge-std/RELEASE_CHECKLIST.md +12 -0
  21. package/lib/forge-std/foundry.toml +18 -0
  22. package/lib/forge-std/package.json +16 -0
  23. package/lib/forge-std/scripts/vm.py +636 -0
  24. package/lib/forge-std/src/Base.sol +48 -0
  25. package/lib/forge-std/src/Config.sol +60 -0
  26. package/lib/forge-std/src/LibVariable.sol +477 -0
  27. package/lib/forge-std/src/Script.sol +28 -0
  28. package/lib/forge-std/src/StdAssertions.sol +779 -0
  29. package/lib/forge-std/src/StdChains.sol +303 -0
  30. package/lib/forge-std/src/StdCheats.sol +825 -0
  31. package/lib/forge-std/src/StdConfig.sol +632 -0
  32. package/lib/forge-std/src/StdConstants.sol +30 -0
  33. package/lib/forge-std/src/StdError.sol +15 -0
  34. package/lib/forge-std/src/StdInvariant.sol +140 -0
  35. package/lib/forge-std/src/StdJson.sol +275 -0
  36. package/lib/forge-std/src/StdMath.sol +47 -0
  37. package/lib/forge-std/src/StdStorage.sol +475 -0
  38. package/lib/forge-std/src/StdStyle.sol +333 -0
  39. package/lib/forge-std/src/StdToml.sol +275 -0
  40. package/lib/forge-std/src/StdUtils.sol +200 -0
  41. package/lib/forge-std/src/Test.sol +32 -0
  42. package/lib/forge-std/src/Vm.sol +2533 -0
  43. package/lib/forge-std/src/console.sol +1551 -0
  44. package/lib/forge-std/src/console2.sol +4 -0
  45. package/lib/forge-std/src/interfaces/IERC1155.sol +105 -0
  46. package/lib/forge-std/src/interfaces/IERC165.sol +12 -0
  47. package/lib/forge-std/src/interfaces/IERC20.sol +43 -0
  48. package/lib/forge-std/src/interfaces/IERC4626.sol +190 -0
  49. package/lib/forge-std/src/interfaces/IERC6909.sol +72 -0
  50. package/lib/forge-std/src/interfaces/IERC721.sol +164 -0
  51. package/lib/forge-std/src/interfaces/IERC7540.sol +144 -0
  52. package/lib/forge-std/src/interfaces/IERC7575.sol +241 -0
  53. package/lib/forge-std/src/interfaces/IMulticall3.sol +68 -0
  54. package/lib/forge-std/src/safeconsole.sol +13248 -0
  55. package/lib/forge-std/test/CommonBase.t.sol +44 -0
  56. package/lib/forge-std/test/Config.t.sol +381 -0
  57. package/lib/forge-std/test/LibVariable.t.sol +452 -0
  58. package/lib/forge-std/test/StdAssertions.t.sol +141 -0
  59. package/lib/forge-std/test/StdChains.t.sol +227 -0
  60. package/lib/forge-std/test/StdCheats.t.sol +638 -0
  61. package/lib/forge-std/test/StdConstants.t.sol +38 -0
  62. package/lib/forge-std/test/StdError.t.sol +119 -0
  63. package/lib/forge-std/test/StdJson.t.sol +49 -0
  64. package/lib/forge-std/test/StdMath.t.sol +202 -0
  65. package/lib/forge-std/test/StdStorage.t.sol +485 -0
  66. package/lib/forge-std/test/StdStyle.t.sol +110 -0
  67. package/lib/forge-std/test/StdToml.t.sol +49 -0
  68. package/lib/forge-std/test/StdUtils.t.sol +342 -0
  69. package/lib/forge-std/test/Vm.t.sol +18 -0
  70. package/lib/forge-std/test/compilation/CompilationScript.sol +8 -0
  71. package/lib/forge-std/test/compilation/CompilationScriptBase.sol +8 -0
  72. package/lib/forge-std/test/compilation/CompilationTest.sol +8 -0
  73. package/lib/forge-std/test/compilation/CompilationTestBase.sol +8 -0
  74. package/lib/forge-std/test/fixtures/broadcast.log.json +187 -0
  75. package/lib/forge-std/test/fixtures/config.toml +81 -0
  76. package/lib/forge-std/test/fixtures/test.json +8 -0
  77. package/lib/forge-std/test/fixtures/test.toml +6 -0
  78. package/package.json +10 -0
  79. package/script/Counter.s.sol +19 -0
  80. package/src/Counter.sol +14 -0
  81. 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
+ }