@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,636 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import argparse
4
+ import copy
5
+ import json
6
+ import re
7
+ import subprocess
8
+ from enum import Enum as PyEnum
9
+ from pathlib import Path
10
+ from typing import Callable
11
+ from urllib import request
12
+
13
+ VoidFn = Callable[[], None]
14
+
15
+ CHEATCODES_JSON_URL = "https://raw.githubusercontent.com/foundry-rs/foundry/master/crates/cheatcodes/assets/cheatcodes.json"
16
+ OUT_PATH = "src/Vm.sol"
17
+
18
+ VM_SAFE_DOC = """\
19
+ /// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
20
+ /// result in Script simulations differing from on-chain execution. It is recommended to only use
21
+ /// these cheats in scripts.
22
+ """
23
+
24
+ VM_DOC = """\
25
+ /// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
26
+ /// in tests, but it is not recommended to use these cheats in scripts.
27
+ """
28
+
29
+
30
+ def main():
31
+ parser = argparse.ArgumentParser(
32
+ description="Generate Vm.sol based on the cheatcodes json created by Foundry")
33
+ parser.add_argument(
34
+ "--from",
35
+ metavar="PATH",
36
+ dest="path",
37
+ required=False,
38
+ help="path to a json file containing the Vm interface, as generated by Foundry")
39
+ args = parser.parse_args()
40
+ json_str = request.urlopen(CHEATCODES_JSON_URL).read().decode("utf-8") if args.path is None else Path(args.path).read_text()
41
+ contract = Cheatcodes.from_json(json_str)
42
+
43
+ ccs = contract.cheatcodes
44
+ ccs = list(filter(lambda cc: cc.status not in ["experimental", "internal"], ccs))
45
+ ccs.sort(key=lambda cc: cc.func.id)
46
+
47
+ safe = list(filter(lambda cc: cc.safety == "safe", ccs))
48
+ safe.sort(key=CmpCheatcode)
49
+ unsafe = list(filter(lambda cc: cc.safety == "unsafe", ccs))
50
+ unsafe.sort(key=CmpCheatcode)
51
+ assert len(safe) + len(unsafe) == len(ccs)
52
+
53
+ prefix_with_group_headers(safe)
54
+ prefix_with_group_headers(unsafe)
55
+
56
+ out = ""
57
+
58
+ out += "// Automatically @generated by scripts/vm.py. Do not modify manually.\n\n"
59
+
60
+ pp = CheatcodesPrinter(
61
+ spdx_identifier="MIT OR Apache-2.0",
62
+ solidity_requirement=">=0.8.13 <0.9.0",
63
+ )
64
+ pp.p_prelude()
65
+ pp.prelude = False
66
+ out += pp.finish()
67
+
68
+ out += "\n\n"
69
+ out += VM_SAFE_DOC
70
+ vm_safe = Cheatcodes(
71
+ # TODO: Custom errors were introduced in 0.8.4
72
+ errors=[], # contract.errors
73
+ events=contract.events,
74
+ enums=contract.enums,
75
+ structs=contract.structs,
76
+ cheatcodes=safe,
77
+ )
78
+ pp.p_contract(vm_safe, "VmSafe")
79
+ out += pp.finish()
80
+
81
+ out += "\n\n"
82
+ out += VM_DOC
83
+ vm_unsafe = Cheatcodes(
84
+ errors=[],
85
+ events=[],
86
+ enums=[],
87
+ structs=[],
88
+ cheatcodes=unsafe,
89
+ )
90
+ pp.p_contract(vm_unsafe, "Vm", "VmSafe")
91
+ out += pp.finish()
92
+
93
+ # Compatibility with <0.8.0
94
+ def memory_to_calldata(m: re.Match) -> str:
95
+ return " calldata " + m.group(1)
96
+
97
+ out = re.sub(r" memory (.*returns)", memory_to_calldata, out)
98
+
99
+ with open(OUT_PATH, "w") as f:
100
+ f.write(out)
101
+
102
+ forge_fmt = ["forge", "fmt", OUT_PATH]
103
+ res = subprocess.run(forge_fmt)
104
+ assert res.returncode == 0, f"command failed: {forge_fmt}"
105
+
106
+ print(f"Wrote to {OUT_PATH}")
107
+
108
+
109
+ class CmpCheatcode:
110
+ cheatcode: "Cheatcode"
111
+
112
+ def __init__(self, cheatcode: "Cheatcode"):
113
+ self.cheatcode = cheatcode
114
+
115
+ def __lt__(self, other: "CmpCheatcode") -> bool:
116
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) < 0
117
+
118
+ def __eq__(self, other: "CmpCheatcode") -> bool:
119
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) == 0
120
+
121
+ def __gt__(self, other: "CmpCheatcode") -> bool:
122
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) > 0
123
+
124
+
125
+ def cmp_cheatcode(a: "Cheatcode", b: "Cheatcode") -> int:
126
+ if a.group != b.group:
127
+ return -1 if a.group < b.group else 1
128
+ if a.status != b.status:
129
+ return -1 if a.status < b.status else 1
130
+ if a.safety != b.safety:
131
+ return -1 if a.safety < b.safety else 1
132
+ if a.func.id != b.func.id:
133
+ return -1 if a.func.id < b.func.id else 1
134
+ return 0
135
+
136
+
137
+ # HACK: A way to add group header comments without having to modify printer code
138
+ def prefix_with_group_headers(cheats: list["Cheatcode"]):
139
+ s = set()
140
+ for i, cheat in enumerate(cheats):
141
+ if cheat.group in s:
142
+ continue
143
+
144
+ s.add(cheat.group)
145
+
146
+ c = copy.deepcopy(cheat)
147
+ c.func.description = ""
148
+ c.func.declaration = f"// ======== {group(c.group)} ========"
149
+ cheats.insert(i, c)
150
+ return cheats
151
+
152
+
153
+ def group(s: str) -> str:
154
+ if s == "evm":
155
+ return "EVM"
156
+ if s == "json":
157
+ return "JSON"
158
+ return s[0].upper() + s[1:]
159
+
160
+
161
+ class Visibility(PyEnum):
162
+ EXTERNAL: str = "external"
163
+ PUBLIC: str = "public"
164
+ INTERNAL: str = "internal"
165
+ PRIVATE: str = "private"
166
+
167
+ def __str__(self):
168
+ return self.value
169
+
170
+
171
+ class Mutability(PyEnum):
172
+ PURE: str = "pure"
173
+ VIEW: str = "view"
174
+ NONE: str = ""
175
+
176
+ def __str__(self):
177
+ return self.value
178
+
179
+
180
+ class Function:
181
+ id: str
182
+ description: str
183
+ declaration: str
184
+ visibility: Visibility
185
+ mutability: Mutability
186
+ signature: str
187
+ selector: str
188
+ selector_bytes: bytes
189
+
190
+ def __init__(
191
+ self,
192
+ id: str,
193
+ description: str,
194
+ declaration: str,
195
+ visibility: Visibility,
196
+ mutability: Mutability,
197
+ signature: str,
198
+ selector: str,
199
+ selector_bytes: bytes,
200
+ ):
201
+ self.id = id
202
+ self.description = description
203
+ self.declaration = declaration
204
+ self.visibility = visibility
205
+ self.mutability = mutability
206
+ self.signature = signature
207
+ self.selector = selector
208
+ self.selector_bytes = selector_bytes
209
+
210
+ @staticmethod
211
+ def from_dict(d: dict) -> "Function":
212
+ return Function(
213
+ d["id"],
214
+ d["description"],
215
+ d["declaration"],
216
+ Visibility(d["visibility"]),
217
+ Mutability(d["mutability"]),
218
+ d["signature"],
219
+ d["selector"],
220
+ bytes(d["selectorBytes"]),
221
+ )
222
+
223
+
224
+ class Cheatcode:
225
+ func: Function
226
+ group: str
227
+ status: str
228
+ safety: str
229
+
230
+ def __init__(self, func: Function, group: str, status: str, safety: str):
231
+ self.func = func
232
+ self.group = group
233
+ self.status = status
234
+ self.safety = safety
235
+
236
+ @staticmethod
237
+ def from_dict(d: dict) -> "Cheatcode":
238
+ return Cheatcode(
239
+ Function.from_dict(d["func"]),
240
+ str(d["group"]),
241
+ str(d["status"]),
242
+ str(d["safety"]),
243
+ )
244
+
245
+
246
+ class Error:
247
+ name: str
248
+ description: str
249
+ declaration: str
250
+
251
+ def __init__(self, name: str, description: str, declaration: str):
252
+ self.name = name
253
+ self.description = description
254
+ self.declaration = declaration
255
+
256
+ @staticmethod
257
+ def from_dict(d: dict) -> "Error":
258
+ return Error(**d)
259
+
260
+
261
+ class Event:
262
+ name: str
263
+ description: str
264
+ declaration: str
265
+
266
+ def __init__(self, name: str, description: str, declaration: str):
267
+ self.name = name
268
+ self.description = description
269
+ self.declaration = declaration
270
+
271
+ @staticmethod
272
+ def from_dict(d: dict) -> "Event":
273
+ return Event(**d)
274
+
275
+
276
+ class EnumVariant:
277
+ name: str
278
+ description: str
279
+
280
+ def __init__(self, name: str, description: str):
281
+ self.name = name
282
+ self.description = description
283
+
284
+
285
+ class Enum:
286
+ name: str
287
+ description: str
288
+ variants: list[EnumVariant]
289
+
290
+ def __init__(self, name: str, description: str, variants: list[EnumVariant]):
291
+ self.name = name
292
+ self.description = description
293
+ self.variants = variants
294
+
295
+ @staticmethod
296
+ def from_dict(d: dict) -> "Enum":
297
+ return Enum(
298
+ d["name"],
299
+ d["description"],
300
+ list(map(lambda v: EnumVariant(**v), d["variants"])),
301
+ )
302
+
303
+
304
+ class StructField:
305
+ name: str
306
+ ty: str
307
+ description: str
308
+
309
+ def __init__(self, name: str, ty: str, description: str):
310
+ self.name = name
311
+ self.ty = ty
312
+ self.description = description
313
+
314
+
315
+ class Struct:
316
+ name: str
317
+ description: str
318
+ fields: list[StructField]
319
+
320
+ def __init__(self, name: str, description: str, fields: list[StructField]):
321
+ self.name = name
322
+ self.description = description
323
+ self.fields = fields
324
+
325
+ @staticmethod
326
+ def from_dict(d: dict) -> "Struct":
327
+ return Struct(
328
+ d["name"],
329
+ d["description"],
330
+ list(map(lambda f: StructField(**f), d["fields"])),
331
+ )
332
+
333
+
334
+ class Cheatcodes:
335
+ errors: list[Error]
336
+ events: list[Event]
337
+ enums: list[Enum]
338
+ structs: list[Struct]
339
+ cheatcodes: list[Cheatcode]
340
+
341
+ def __init__(
342
+ self,
343
+ errors: list[Error],
344
+ events: list[Event],
345
+ enums: list[Enum],
346
+ structs: list[Struct],
347
+ cheatcodes: list[Cheatcode],
348
+ ):
349
+ self.errors = errors
350
+ self.events = events
351
+ self.enums = enums
352
+ self.structs = structs
353
+ self.cheatcodes = cheatcodes
354
+
355
+ @staticmethod
356
+ def from_dict(d: dict) -> "Cheatcodes":
357
+ return Cheatcodes(
358
+ errors=[Error.from_dict(e) for e in d["errors"]],
359
+ events=[Event.from_dict(e) for e in d["events"]],
360
+ enums=[Enum.from_dict(e) for e in d["enums"]],
361
+ structs=[Struct.from_dict(e) for e in d["structs"]],
362
+ cheatcodes=[Cheatcode.from_dict(e) for e in d["cheatcodes"]],
363
+ )
364
+
365
+ @staticmethod
366
+ def from_json(s) -> "Cheatcodes":
367
+ return Cheatcodes.from_dict(json.loads(s))
368
+
369
+ @staticmethod
370
+ def from_json_file(file_path: str) -> "Cheatcodes":
371
+ with open(file_path, "r") as f:
372
+ return Cheatcodes.from_dict(json.load(f))
373
+
374
+
375
+ class Item(PyEnum):
376
+ ERROR: str = "error"
377
+ EVENT: str = "event"
378
+ ENUM: str = "enum"
379
+ STRUCT: str = "struct"
380
+ FUNCTION: str = "function"
381
+
382
+
383
+ class ItemOrder:
384
+ _list: list[Item]
385
+
386
+ def __init__(self, list: list[Item]) -> None:
387
+ assert len(list) <= len(Item), "list must not contain more items than Item"
388
+ assert len(list) == len(set(list)), "list must not contain duplicates"
389
+ self._list = list
390
+ pass
391
+
392
+ def get_list(self) -> list[Item]:
393
+ return self._list
394
+
395
+ @staticmethod
396
+ def default() -> "ItemOrder":
397
+ return ItemOrder(
398
+ [
399
+ Item.ERROR,
400
+ Item.EVENT,
401
+ Item.ENUM,
402
+ Item.STRUCT,
403
+ Item.FUNCTION,
404
+ ]
405
+ )
406
+
407
+
408
+ class CheatcodesPrinter:
409
+ buffer: str
410
+
411
+ prelude: bool
412
+ spdx_identifier: str
413
+ solidity_requirement: str
414
+
415
+ block_doc_style: bool
416
+
417
+ indent_level: int
418
+ _indent_str: str
419
+
420
+ nl_str: str
421
+
422
+ items_order: ItemOrder
423
+
424
+ def __init__(
425
+ self,
426
+ buffer: str = "",
427
+ prelude: bool = True,
428
+ spdx_identifier: str = "UNLICENSED",
429
+ solidity_requirement: str = "",
430
+ block_doc_style: bool = False,
431
+ indent_level: int = 0,
432
+ indent_with: int | str = 4,
433
+ nl_str: str = "\n",
434
+ items_order: ItemOrder = ItemOrder.default(),
435
+ ):
436
+ self.prelude = prelude
437
+ self.spdx_identifier = spdx_identifier
438
+ self.solidity_requirement = solidity_requirement
439
+ self.block_doc_style = block_doc_style
440
+ self.buffer = buffer
441
+ self.indent_level = indent_level
442
+ self.nl_str = nl_str
443
+
444
+ if isinstance(indent_with, int):
445
+ assert indent_with >= 0
446
+ self._indent_str = " " * indent_with
447
+ elif isinstance(indent_with, str):
448
+ self._indent_str = indent_with
449
+ else:
450
+ assert False, "indent_with must be int or str"
451
+
452
+ self.items_order = items_order
453
+
454
+ def finish(self) -> str:
455
+ ret = self.buffer.rstrip()
456
+ self.buffer = ""
457
+ return ret
458
+
459
+ def p_contract(self, contract: Cheatcodes, name: str, inherits: str = ""):
460
+ if self.prelude:
461
+ self.p_prelude(contract)
462
+
463
+ self._p_str("interface ")
464
+ name = name.strip()
465
+ if name != "":
466
+ self._p_str(name)
467
+ self._p_str(" ")
468
+ if inherits != "":
469
+ self._p_str("is ")
470
+ self._p_str(inherits)
471
+ self._p_str(" ")
472
+ self._p_str("{")
473
+ self._p_nl()
474
+ self._with_indent(lambda: self._p_items(contract))
475
+ self._p_str("}")
476
+ self._p_nl()
477
+
478
+ def _p_items(self, contract: Cheatcodes):
479
+ for item in self.items_order.get_list():
480
+ if item == Item.ERROR:
481
+ self.p_errors(contract.errors)
482
+ elif item == Item.EVENT:
483
+ self.p_events(contract.events)
484
+ elif item == Item.ENUM:
485
+ self.p_enums(contract.enums)
486
+ elif item == Item.STRUCT:
487
+ self.p_structs(contract.structs)
488
+ elif item == Item.FUNCTION:
489
+ self.p_functions(contract.cheatcodes)
490
+ else:
491
+ assert False, f"unknown item {item}"
492
+
493
+ def p_prelude(self, contract: Cheatcodes | None = None):
494
+ self._p_str(f"// SPDX-License-Identifier: {self.spdx_identifier}")
495
+ self._p_nl()
496
+
497
+ if self.solidity_requirement != "":
498
+ req = self.solidity_requirement
499
+ else:
500
+ req = ">=0.8.13 <0.9.0"
501
+ self._p_str(f"pragma solidity {req};")
502
+ self._p_nl()
503
+
504
+ self._p_nl()
505
+
506
+ def p_errors(self, errors: list[Error]):
507
+ for error in errors:
508
+ self._p_line(lambda: self.p_error(error))
509
+
510
+ def p_error(self, error: Error):
511
+ self._p_comment(error.description, doc=True)
512
+ self._p_line(lambda: self._p_str(error.declaration))
513
+
514
+ def p_events(self, events: list[Event]):
515
+ for event in events:
516
+ self._p_line(lambda: self.p_event(event))
517
+
518
+ def p_event(self, event: Event):
519
+ self._p_comment(event.description, doc=True)
520
+ self._p_line(lambda: self._p_str(event.declaration))
521
+
522
+ def p_enums(self, enums: list[Enum]):
523
+ for enum in enums:
524
+ self._p_line(lambda: self.p_enum(enum))
525
+
526
+ def p_enum(self, enum: Enum):
527
+ self._p_comment(enum.description, doc=True)
528
+ self._p_line(lambda: self._p_str(f"enum {enum.name} {{"))
529
+ self._with_indent(lambda: self.p_enum_variants(enum.variants))
530
+ self._p_line(lambda: self._p_str("}"))
531
+
532
+ def p_enum_variants(self, variants: list[EnumVariant]):
533
+ for i, variant in enumerate(variants):
534
+ self._p_indent()
535
+ self._p_comment(variant.description)
536
+
537
+ self._p_indent()
538
+ self._p_str(variant.name)
539
+ if i < len(variants) - 1:
540
+ self._p_str(",")
541
+ self._p_nl()
542
+
543
+ def p_structs(self, structs: list[Struct]):
544
+ for struct in structs:
545
+ self._p_line(lambda: self.p_struct(struct))
546
+
547
+ def p_struct(self, struct: Struct):
548
+ self._p_comment(struct.description, doc=True)
549
+ self._p_line(lambda: self._p_str(f"struct {struct.name} {{"))
550
+ self._with_indent(lambda: self.p_struct_fields(struct.fields))
551
+ self._p_line(lambda: self._p_str("}"))
552
+
553
+ def p_struct_fields(self, fields: list[StructField]):
554
+ for field in fields:
555
+ self._p_line(lambda: self.p_struct_field(field))
556
+
557
+ def p_struct_field(self, field: StructField):
558
+ self._p_comment(field.description)
559
+ self._p_indented(lambda: self._p_str(f"{field.ty} {field.name};"))
560
+
561
+ def p_functions(self, cheatcodes: list[Cheatcode]):
562
+ for cheatcode in cheatcodes:
563
+ self._p_line(lambda: self.p_function(cheatcode.func))
564
+
565
+ def p_function(self, func: Function):
566
+ self._p_comment(func.description, doc=True)
567
+ self._p_line(lambda: self._p_str(func.declaration))
568
+
569
+ def _p_comment(self, s: str, doc: bool = False):
570
+ s = s.strip()
571
+ if s == "":
572
+ return
573
+
574
+ s = map(lambda line: line.lstrip(), s.split("\n"))
575
+ if self.block_doc_style:
576
+ self._p_str("/*")
577
+ if doc:
578
+ self._p_str("*")
579
+ self._p_nl()
580
+ for line in s:
581
+ self._p_indent()
582
+ self._p_str(" ")
583
+ if doc:
584
+ self._p_str("* ")
585
+ self._p_str(line)
586
+ self._p_nl()
587
+ self._p_indent()
588
+ self._p_str(" */")
589
+ self._p_nl()
590
+ else:
591
+ first_line = True
592
+ for line in s:
593
+ if not first_line:
594
+ self._p_indent()
595
+ first_line = False
596
+
597
+ if doc:
598
+ self._p_str("/// ")
599
+ else:
600
+ self._p_str("// ")
601
+ self._p_str(line)
602
+ self._p_nl()
603
+
604
+ def _with_indent(self, f: VoidFn):
605
+ self._inc_indent()
606
+ f()
607
+ self._dec_indent()
608
+
609
+ def _p_line(self, f: VoidFn):
610
+ self._p_indent()
611
+ f()
612
+ self._p_nl()
613
+
614
+ def _p_indented(self, f: VoidFn):
615
+ self._p_indent()
616
+ f()
617
+
618
+ def _p_indent(self):
619
+ for _ in range(self.indent_level):
620
+ self._p_str(self._indent_str)
621
+
622
+ def _p_nl(self):
623
+ self._p_str(self.nl_str)
624
+
625
+ def _p_str(self, txt: str):
626
+ self.buffer += txt
627
+
628
+ def _inc_indent(self):
629
+ self.indent_level += 1
630
+
631
+ def _dec_indent(self):
632
+ self.indent_level -= 1
633
+
634
+
635
+ if __name__ == "__main__":
636
+ main()
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: MIT OR Apache-2.0
2
+ pragma solidity >=0.8.13 <0.9.0;
3
+
4
+ import {StdStorage} from "./StdStorage.sol";
5
+ import {Vm, VmSafe} from "./Vm.sol";
6
+
7
+ abstract contract CommonBase {
8
+ /// @dev Cheat code address.
9
+ /// Calculated as `address(uint160(uint256(keccak256("hevm cheat code"))))`.
10
+ address internal constant VM_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
11
+
12
+ /// @dev console.sol and console2.sol work by executing a staticcall to this address.
13
+ /// Calculated as `address(uint160(uint88(bytes11("console.log"))))`.
14
+ address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
15
+
16
+ /// @dev Used when deploying with create2.
17
+ /// Taken from https://github.com/Arachnid/deterministic-deployment-proxy.
18
+ address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
19
+
20
+ /// @dev The default address for tx.origin and msg.sender.
21
+ /// Calculated as `address(uint160(uint256(keccak256("foundry default caller"))))`.
22
+ address internal constant DEFAULT_SENDER = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
23
+
24
+ /// @dev The address of the first contract `CREATE`d by a running test contract.
25
+ /// When running tests, each test contract is `CREATE`d by `DEFAULT_SENDER` with nonce 1.
26
+ /// Calculated as `VM.computeCreateAddress(VM.computeCreateAddress(DEFAULT_SENDER, 1), 1)`.
27
+ address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
28
+
29
+ /// @dev Deterministic deployment address of the Multicall3 contract.
30
+ /// Taken from https://www.multicall3.com.
31
+ address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
32
+
33
+ /// @dev The order of the secp256k1 curve.
34
+ uint256 internal constant SECP256K1_ORDER =
35
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
36
+
37
+ uint256 internal constant UINT256_MAX =
38
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
39
+
40
+ Vm internal constant vm = Vm(VM_ADDRESS);
41
+ StdStorage internal stdstore;
42
+ }
43
+
44
+ abstract contract TestBase is CommonBase {}
45
+
46
+ abstract contract ScriptBase is CommonBase {
47
+ VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
48
+ }