certora-cli 6.3.1__tar.gz → 7.3.0__tar.gz

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 (67) hide show
  1. {certora-cli-6.3.1/certora_cli.egg-info → certora-cli-7.3.0}/PKG-INFO +2 -2
  2. certora-cli-7.3.0/README.md +1 -0
  3. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +41 -32
  4. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +8 -2
  5. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +29 -17
  6. certora-cli-7.3.0/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +21 -0
  7. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +109 -51
  8. certora-cli-7.3.0/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +90 -0
  9. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraBuild.py +323 -241
  10. certora-cli-7.3.0/certora_cli/EVMVerifier/certoraCompilerParameters.py +22 -0
  11. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraConfigIO.py +6 -6
  12. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContext.py +19 -12
  13. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextAttribute.py +151 -49
  14. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextValidator.py +113 -136
  15. certora-cli-7.3.0/certora_cli/EVMVerifier/certoraContractFuncs.py +121 -0
  16. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraType.py +2 -0
  17. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/equivCheck.py +4 -2
  18. certora-cli-7.3.0/certora_cli/Mutate/mutateApp.py +1750 -0
  19. certora-cli-7.3.0/certora_cli/Mutate/mutateAttribute.py +314 -0
  20. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Mutate/mutateConstants.py +35 -9
  21. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Mutate/mutateValidate.py +45 -58
  22. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/ExpectedComparator.py +32 -15
  23. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/certoraAttrUtil.py +13 -22
  24. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/certoraUtils.py +123 -29
  25. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/certoraValidateFuncs.py +59 -12
  26. certora-cli-7.3.0/certora_cli/certoraMutate.py +94 -0
  27. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/certoraRun.py +6 -11
  28. {certora-cli-6.3.1 → certora-cli-7.3.0/certora_cli.egg-info}/PKG-INFO +2 -2
  29. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli.egg-info/SOURCES.txt +4 -1
  30. certora-cli-7.3.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
  31. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_jars/Typechecker.jar +0 -0
  32. {certora-cli-6.3.1 → certora-cli-7.3.0}/setup.py +2 -2
  33. certora-cli-6.3.1/README.md +0 -1
  34. certora-cli-6.3.1/certora_cli/EVMVerifier/certoraMutateGenerator.py +0 -133
  35. certora-cli-6.3.1/certora_cli/Mutate/mutateApp.py +0 -1347
  36. certora-cli-6.3.1/certora_cli/Mutate/mutateAttribute.py +0 -227
  37. certora-cli-6.3.1/certora_cli/certoraMutate.py +0 -72
  38. certora-cli-6.3.1/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
  39. {certora-cli-6.3.1 → certora-cli-7.3.0}/LICENSE +0 -0
  40. {certora-cli-6.3.1 → certora-cli-7.3.0}/MANIFEST.in +0 -0
  41. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_bins/__init__.py +0 -0
  42. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
  43. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/__init__.py +0 -0
  44. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraCloudIO.py +0 -0
  45. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +0 -0
  46. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
  47. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
  48. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
  49. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
  50. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
  51. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
  52. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
  53. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
  54. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
  55. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/__init__.py +0 -0
  56. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
  57. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Mutate/__init__.py +0 -0
  58. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/__init__.py +0 -0
  59. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/Shared/certoraLogging.py +0 -0
  60. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/__init__.py +0 -0
  61. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli/certoraEqCheck.py +0 -0
  62. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli.egg-info/dependency_links.txt +0 -0
  63. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli.egg-info/entry_points.txt +0 -0
  64. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli.egg-info/requires.txt +0 -0
  65. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_cli.egg-info/top_level.txt +0 -0
  66. {certora-cli-6.3.1 → certora-cli-7.3.0}/certora_jars/__init__.py +0 -0
  67. {certora-cli-6.3.1 → certora-cli-7.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: certora-cli
3
- Version: 6.3.1
3
+ Version: 7.3.0
4
4
  Summary: Runner for the Certora Prover
5
5
  Home-page: https://pypi.org/project/certora-cli
6
6
  Author: Certora
@@ -21,4 +21,4 @@ Requires-Dist: tabulate
21
21
  Requires-Dist: tqdm
22
22
  Requires-Dist: StrEnum
23
23
 
24
- Commit 1c08d79. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
24
+ Commit 3dce873. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -0,0 +1 @@
1
+ Commit 3dce873. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -1,4 +1,5 @@
1
1
  from abc import abstractmethod, ABC
2
+ from dataclasses import dataclass
2
3
  from pathlib import Path
3
4
  from typing import Any, Dict, List, Optional, Tuple, Set
4
5
  from Shared.certoraUtils import AbstractAndSingleton, CompilerVersion
@@ -6,39 +7,23 @@ import EVMVerifier.certoraType as CT
6
7
 
7
8
 
8
9
  # TODO: merge this with Func in certoraBuild
10
+ @dataclass
9
11
  class CompilerLangFunc:
10
- def __init__(self,
11
- name: str,
12
- fullargs: List[CT.TypeInstance],
13
- paramnames: List[str],
14
- returns: List[CT.TypeInstance],
15
- sighash: str,
16
- notpayable: bool,
17
- fromlib: bool, # not serialized
18
- isconstructor: bool, # not serialized
19
- statemutability: str,
20
- visibility: str,
21
- implemented: bool, # does this function have a body? (false for interface functions)
22
- overrides: bool, # does this function override an interface declaration or super-contract definition?
23
- contractName: str,
24
- ast_id: Optional[int] = None,
25
- where: Optional[Tuple[str, str]] = None # 1st element: source file name, 2nd element: location string
26
- ):
27
- self.name = name
28
- self.fullArgs = fullargs
29
- self.paramNames = paramnames
30
- self.returns = returns
31
- self.sighash = sighash
32
- self.notpayable = notpayable
33
- self.fromLib = fromlib
34
- self.isConstructor = isconstructor
35
- self.stateMutability = statemutability
36
- self.visibility = visibility
37
- self.where = where
38
- self.implemented = implemented
39
- self.ast_id = ast_id
40
- self.overrides = overrides
41
- self.contractName = contractName
12
+ name: str
13
+ fullArgs: List[CT.TypeInstance]
14
+ paramNames: List[str]
15
+ returns: List[CT.TypeInstance]
16
+ sighash: str
17
+ notpayable: bool
18
+ fromLib: bool # not serialized
19
+ isConstructor: bool # not serialized
20
+ stateMutability: str
21
+ visibility: str
22
+ implemented: bool # does this function have a body? (false for interface functions)
23
+ overrides: bool # does this function override an interface declaration or super-contract definition?
24
+ contractName: str
25
+ ast_id: Optional[int] = None
26
+ where: Optional[Tuple[str, str]] = None # 1st element: source file name, 2nd element: location string
42
27
 
43
28
 
44
29
  class CompilerLang(metaclass=AbstractAndSingleton):
@@ -146,6 +131,30 @@ class CompilerLang(metaclass=AbstractAndSingleton):
146
131
  """
147
132
  pass
148
133
 
134
+ @property
135
+ @abstractmethod
136
+ def supports_typed_immutables(self) -> bool:
137
+ """
138
+ :return: True if has type information associated to immutables
139
+ """
140
+ pass
141
+
142
+ @property
143
+ @abstractmethod
144
+ def supports_ast_output(self) -> bool:
145
+ """
146
+ :return: True if compiling contracts in this language produces AST output
147
+ """
148
+ pass
149
+
150
+ @property
151
+ @abstractmethod
152
+ def supports_srclist_output(self) -> bool:
153
+ """
154
+ :return: True if compiling contracts in this language produces srclist output
155
+ """
156
+ pass
157
+
149
158
 
150
159
  class CompilerCollector(ABC):
151
160
  """
@@ -9,6 +9,7 @@ import re
9
9
  import logging
10
10
  from EVMVerifier.Compiler.CompilerCollector import CompilerLang, CompilerCollector
11
11
  from EVMVerifier.Compiler.CompilerCollectorSol import CompilerCollectorSol, CompilerLangSol
12
+ from EVMVerifier.Compiler.CompilerCollectorYul import CompilerLangYul, CompilerCollectorYul
12
13
  from EVMVerifier.Compiler.CompilerCollectorVy import CompilerCollectorVy, CompilerLangVy
13
14
  from Shared.certoraUtils import is_windows, match_path_to_mapping_key, remove_file, get_certora_config_dir
14
15
  from EVMVerifier.certoraContextClass import CertoraContext
@@ -71,9 +72,12 @@ class CompilerCollectorFactory:
71
72
  return CompilerCollectorVy(version)
72
73
  elif str(path).endswith(".sol"):
73
74
  version = self.__get_solc_version(path)
74
- return CompilerCollectorSol(version)
75
+ return CompilerCollectorSol(version, CompilerLangSol(), self.context.use_memory_safe_autofinders)
76
+ elif str(path).endswith(".yul"):
77
+ version = self.__get_solc_version(path)
78
+ return CompilerCollectorYul(version, CompilerLangYul())
75
79
  else:
76
- raise RuntimeError(f'expected {path} to represent a Solidity or Vyper file')
80
+ raise RuntimeError(f'expected {path} to represent a Solidity, Yul, or Vyper file')
77
81
 
78
82
  @staticmethod
79
83
  def get_vyper_compiler(contract_file_path: Path, default_compiler: str, compiler_mappings: Dict[str, str]) -> str:
@@ -170,5 +174,7 @@ def get_compiler_lang(file_name: str) -> CompilerLang:
170
174
  return CompilerLangVy()
171
175
  elif file_name.endswith(".sol"):
172
176
  return CompilerLangSol()
177
+ elif file_name.endswith(".yul"):
178
+ return CompilerLangYul()
173
179
  else:
174
180
  raise RuntimeError(f'expected {file_name} to represent a Solidity or Vyper file')
@@ -1,7 +1,8 @@
1
1
  from pathlib import Path
2
2
  from typing import Any, List, Tuple, Dict, Set
3
3
 
4
- from EVMVerifier.Compiler.CompilerCollector import CompilerLang, CompilerCollector, CompilerLangFunc
4
+ from EVMVerifier.Compiler.CompilerCollector import CompilerLang, CompilerLangFunc
5
+ from EVMVerifier.Compiler.CompilerCollectorSolBased import CompilerCollectorSolBased
5
6
  from Shared.certoraUtils import Singleton, CompilerVersion, get_certora_config_dir
6
7
  import EVMVerifier.certoraType as CT
7
8
 
@@ -62,33 +63,44 @@ class CompilerLangSol(CompilerLang, metaclass=Singleton):
62
63
  Tuple[List[CT.Type], List[CompilerLangFunc]]:
63
64
  assert False, "collect_source_type_descriptions() has not yet been implemented in CompilerLangSol"
64
65
 
65
-
66
- # This class is intended for calculations of compiler-settings related queries
67
- class CompilerCollectorSol(CompilerCollector):
68
-
69
- def __init__(self, version: CompilerVersion):
70
- self.__compiler_version = version
71
-
72
66
  @property
73
- def compiler_name(self) -> str:
74
- return self.smart_contract_lang.compiler_name
67
+ def supports_typed_immutables(self) -> bool:
68
+ return True
75
69
 
76
70
  @property
77
- def smart_contract_lang(self) -> CompilerLangSol:
78
- return CompilerLangSol()
71
+ def supports_ast_output(self) -> bool:
72
+ return True
79
73
 
80
74
  @property
81
- def compiler_version(self) -> CompilerVersion:
82
- return self.__compiler_version
75
+ def supports_srclist_output(self) -> bool:
76
+ return True
77
+
78
+
79
+ # This class is intended for calculations of compiler-settings related queries
80
+ class CompilerCollectorSol(CompilerCollectorSolBased):
81
+
82
+ def __init__(self, version: CompilerVersion, lang: CompilerLang, use_memory_safe_autofinders: bool):
83
+ super().__init__(version, lang)
84
+ self.__use_memory_safe_autofinders = use_memory_safe_autofinders
83
85
 
84
86
  def normalize_storage(self, is_storage: bool, arg_name: str) -> str:
85
87
  if not is_storage:
86
88
  return arg_name
87
- if self.__compiler_version[0] == 0 and self.__compiler_version[1] < 7:
89
+ if self.compiler_version[0] == 0 and self.compiler_version[1] < 7:
88
90
  return arg_name + "_slot"
89
91
  else:
90
92
  return arg_name + ".slot"
91
93
 
92
94
  def supports_calldata_assembly(self, arg_name: str) -> bool:
93
- return (self.__compiler_version[1] > 7 or (
94
- self.__compiler_version[1] == 7 and self.__compiler_version[2] >= 5)) and arg_name != ""
95
+ return (self.compiler_version[1] > 7 or (
96
+ self.compiler_version[1] == 7 and self.compiler_version[2] >= 5)) and arg_name != ""
97
+
98
+ def supports_memory_safe_assembly(self) -> bool:
99
+ return (self.compiler_version[1] > 8 or (
100
+ self.compiler_version[1] == 8 and self.compiler_version[2] >= 13))
101
+
102
+ def gen_memory_safe_assembly_prefix(self) -> str:
103
+ if self.supports_memory_safe_assembly() and self.__use_memory_safe_autofinders:
104
+ return 'assembly ("memory-safe")'
105
+ else:
106
+ return 'assembly'
@@ -0,0 +1,21 @@
1
+ from EVMVerifier.Compiler.CompilerCollector import CompilerCollector, CompilerLang
2
+ from Shared.certoraUtils import CompilerVersion
3
+
4
+
5
+ class CompilerCollectorSolBased(CompilerCollector):
6
+
7
+ def __init__(self, version: CompilerVersion, lang: CompilerLang):
8
+ self.__compiler_version = version
9
+ self.__smart_contract_lang = lang
10
+
11
+ @property
12
+ def compiler_name(self) -> str:
13
+ return self.smart_contract_lang.compiler_name
14
+
15
+ @property
16
+ def smart_contract_lang(self) -> CompilerLang:
17
+ return self.__smart_contract_lang
18
+
19
+ @property
20
+ def compiler_version(self) -> CompilerVersion:
21
+ return self.__compiler_version
@@ -80,6 +80,10 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
80
80
  return {CompilerLangVy.compilation_output_path(sdc_name),
81
81
  CompilerLangVy.compilation_error_path(sdc_name)}
82
82
 
83
+ @staticmethod
84
+ def pad(x: int) -> int:
85
+ return (x + 31) & ~31
86
+
83
87
  class VyperType(ABC):
84
88
  uniqueId: int = 0
85
89
 
@@ -90,11 +94,11 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
90
94
  return r
91
95
 
92
96
  @abstractmethod
93
- def size_in_bytes(self) -> int:
97
+ def size_in_bytes(self, storage: bool = False) -> int:
94
98
  pass
95
99
 
96
100
  @abstractmethod
97
- def generate_types_field(self) -> Dict[str, Any]:
101
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
98
102
  """Returns a JSON-style object containing the fields of a [bridge.SolcType] (in kotlin)"""
99
103
  pass
100
104
 
@@ -126,10 +130,10 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
126
130
  def __init__(self, name: str):
127
131
  self.name = name
128
132
 
129
- def size_in_bytes(self) -> int:
133
+ def size_in_bytes(self, storage: bool = False) -> int:
130
134
  raise NotImplementedError
131
135
 
132
- def generate_types_field(self) -> Dict[str, Any]:
136
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
133
137
  raise NotImplementedError
134
138
 
135
139
  def get_canonical_vyper_name(self) -> str:
@@ -154,15 +158,21 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
154
158
  self.element_type = element_type
155
159
  self.max_num_elements = max_num_elements
156
160
 
157
- def size_in_bytes(self) -> int:
158
- return self.element_type.size_in_bytes() * self.max_num_elements
161
+ def size_in_bytes(self, storage: bool = False) -> int:
162
+ element_size = self.element_type.size_in_bytes(storage)
163
+ # bytes _are_ actually packed in storage arrays
164
+ if storage and self.element_type != CompilerLangVy.primitive_types['byte']:
165
+ element_size = CompilerLangVy.pad(element_size)
166
+ return element_size * self.max_num_elements
167
+ else:
168
+ return CompilerLangVy.pad(element_size * self.max_num_elements)
159
169
 
160
- def generate_types_field(self) -> Dict[str, Any]:
170
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
161
171
  return {
162
172
  'label': self.get_canonical_vyper_name(),
163
173
  'encoding': 'inplace',
164
174
  'base': self.element_type.get_canonical_vyper_name(),
165
- 'numberOfBytes': str(self.size_in_bytes())
175
+ 'numberOfBytes': str(self.size_in_bytes(storage))
166
176
  }
167
177
 
168
178
  def get_canonical_vyper_name(self) -> str:
@@ -173,7 +183,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
173
183
  return self
174
184
 
175
185
  def get_used_types(self) -> List[Any]:
176
- return [self] + [self.element_type]
186
+ return [self] + self.element_type.get_used_types()
177
187
 
178
188
  def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
179
189
  return CT.ArrayType(self.element_type.get_canonical_vyper_name(),
@@ -193,14 +203,14 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
193
203
  self.name = name
194
204
  self.members = members
195
205
 
196
- def size_in_bytes(self) -> int:
206
+ def size_in_bytes(self, storage: bool = False) -> int:
197
207
  return 1
198
208
 
199
- def generate_types_field(self) -> Dict[str, Any]:
209
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
200
210
  return {
201
211
  'label': self.get_canonical_vyper_name(),
202
212
  'encoding': 'inplace',
203
- 'numberOfBytes': str(self.size_in_bytes())
213
+ 'numberOfBytes': str(self.size_in_bytes(storage))
204
214
  }
205
215
 
206
216
  def get_canonical_vyper_name(self) -> str:
@@ -227,15 +237,20 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
227
237
  self.name = name
228
238
  self.members = members
229
239
 
230
- def size_in_bytes(self) -> int:
231
- return sum([f[1].size_in_bytes() for f in self.members])
240
+ def size_in_bytes(self, storage: bool = False) -> int:
241
+ def mem_size(f: Tuple[str, Any]) -> int:
242
+ sz = f[1].size_in_bytes(storage)
243
+ if storage:
244
+ sz = CompilerLangVy.pad(sz)
245
+ return sz
246
+ return sum([mem_size(f) for f in self.members])
232
247
 
233
- def generate_types_field(self) -> Dict[str, Any]:
248
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
234
249
  bytes_so_far_rounded_up = 0
235
250
  slots = {}
236
251
  for n, t in self.members:
237
252
  slots.update({n: bytes_so_far_rounded_up // 32})
238
- bytes_so_far_rounded_up += (t.size_in_bytes() + 31) & ~31
253
+ bytes_so_far_rounded_up += CompilerLangVy.pad(t.size_in_bytes(storage))
239
254
  members_field = [
240
255
  {
241
256
  'label': n,
@@ -248,7 +263,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
248
263
  'label': self.get_canonical_vyper_name(),
249
264
  'encoding': 'inplace',
250
265
  'members': members_field,
251
- 'numberOfBytes': str(self.size_in_bytes())
266
+ 'numberOfBytes': str(self.size_in_bytes(storage))
252
267
  }
253
268
 
254
269
  def get_canonical_vyper_name(self) -> str:
@@ -282,12 +297,12 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
282
297
  self.max_num_elements = max_num_elements
283
298
 
284
299
  self.count_type = CompilerLangVy.VyperTypeBoundedInteger(
285
- CompilerLangVy.primitive_types['uint256'], 1, max_num_elements)
300
+ CompilerLangVy.primitive_types['uint256'], 0, max_num_elements)
286
301
  self.array_type = CompilerLangVy.VyperTypeStaticArray(element_type, int(max_num_elements))
287
302
  super().__init__(self.get_canonical_vyper_name(), [('count', self.count_type), ('data', self.array_type)])
288
303
 
289
304
  def get_canonical_vyper_name(self) -> str:
290
- return f"DynArray[{self.element_type.get_canonical_vyper_name()},{self.max_num_elements}]"
305
+ return f"DynArray[{self.element_type.get_canonical_vyper_name()}, {self.max_num_elements}]"
291
306
 
292
307
  def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
293
308
  element_type = self.element_type.get_certora_type(contract_name, ref)
@@ -308,15 +323,25 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
308
323
  def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
309
324
  return CT.StringType()
310
325
 
326
+ class VyperTypeBytes(VyperTypeDynArray):
327
+ def __init__(self, max_num_elements: int):
328
+ super().__init__(CompilerLangVy.primitive_types['byte'], max_num_elements)
329
+
330
+ def get_canonical_vyper_name(self) -> str:
331
+ return 'Bytes[' + str(self.array_type.max_num_elements) + ']'
332
+
333
+ def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
334
+ return CT.PackedBytes()
335
+
311
336
  class VyperTypeHashMap(VyperType):
312
337
  def __init__(self, key_type: Any, value_type: Any):
313
338
  self.key_type = key_type
314
339
  self.value_type = value_type
315
340
 
316
- def size_in_bytes(self) -> int:
341
+ def size_in_bytes(self, storage: bool = False) -> int:
317
342
  return 32
318
343
 
319
- def generate_types_field(self) -> Dict[str, Any]:
344
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
320
345
  return {
321
346
  'label': self.get_canonical_vyper_name(),
322
347
  'encoding': 'mapping',
@@ -335,7 +360,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
335
360
  return self
336
361
 
337
362
  def get_used_types(self) -> List[Any]:
338
- return [self] + [self.key_type] + [self.value_type]
363
+ return [self] + self.key_type.get_used_types() + self.value_type.get_used_types()
339
364
 
340
365
  def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
341
366
  in_type = self.key_type.get_certora_type(contract_name, ref)
@@ -353,17 +378,17 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
353
378
  def __init__(self, name: str):
354
379
  self.name = name
355
380
 
356
- def size_in_bytes(self) -> int:
381
+ def size_in_bytes(self, storage: bool = False) -> int:
357
382
  return 20
358
383
 
359
384
  def get_canonical_vyper_name(self) -> str:
360
385
  return self.name
361
386
 
362
- def generate_types_field(self) -> Dict[str, Any]:
387
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
363
388
  return {
364
389
  'label': "contract " + self.get_canonical_vyper_name(),
365
390
  'encoding': 'inplace',
366
- 'numberOfBytes': str(self.size_in_bytes())
391
+ 'numberOfBytes': str(self.size_in_bytes(storage))
367
392
  }
368
393
 
369
394
  def get_certora_type(self, contract_name: str, ref: int) -> CT.Type:
@@ -380,14 +405,14 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
380
405
  self.name = name
381
406
  self.size = size
382
407
 
383
- def size_in_bytes(self) -> int:
408
+ def size_in_bytes(self, storage: bool = False) -> int:
384
409
  return self.size
385
410
 
386
- def generate_types_field(self) -> Dict[str, Any]:
411
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
387
412
  return {
388
413
  'label': self.get_canonical_vyper_name(),
389
414
  'encoding': 'inplace',
390
- 'numberOfBytes': str(self.size_in_bytes())
415
+ 'numberOfBytes': str(self.size_in_bytes(storage))
391
416
  }
392
417
 
393
418
  def get_canonical_vyper_name(self) -> str:
@@ -428,11 +453,11 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
428
453
  self.lower_bound = lower_bound
429
454
  self.upper_bound = upper_bound
430
455
 
431
- def generate_types_field(self) -> Dict[str, Any]:
456
+ def generate_types_field(self, storage: bool = False) -> Dict[str, Any]:
432
457
  return {
433
458
  'label': self.get_canonical_vyper_name(),
434
459
  'encoding': 'inplace',
435
- 'numberOfBytes': str(self.size_in_bytes()),
460
+ 'numberOfBytes': str(self.size_in_bytes(storage)),
436
461
  'lowerBound': str(self.lower_bound),
437
462
  'upperBound': str(self.upper_bound)
438
463
  }
@@ -464,6 +489,20 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
464
489
  **build_sequence(lambda i: f"bytes{i}", lambda i: 32 + i) # type: ignore
465
490
  }
466
491
 
492
+ vyper_constructor_name = "__init__"
493
+
494
+ @property
495
+ def supports_typed_immutables(self) -> bool:
496
+ return True
497
+
498
+ @property
499
+ def supports_ast_output(self) -> bool:
500
+ return True
501
+
502
+ @property
503
+ def supports_srclist_output(self) -> bool:
504
+ return True
505
+
467
506
  @staticmethod
468
507
  def extract_constant(ast_node: Dict[str, Any], named_constants: Dict[str, int]) -> int:
469
508
  """
@@ -509,6 +548,9 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
509
548
  if value_id == 'String':
510
549
  max_bytes = ast_subscript_node['slice']['value']['value']
511
550
  return CompilerLangVy.VyperTypeString(max_bytes)
551
+ elif value_id == 'Bytes':
552
+ max_bytes = ast_subscript_node['slice']['value']['value']
553
+ return CompilerLangVy.VyperTypeBytes(max_bytes)
512
554
  elif value_id == 'DynArray':
513
555
  elem_type = CompilerLangVy.extract_type_from_type_annotation_node(
514
556
  ast_subscript_node['slice']['value']['elements'][0], named_constants)
@@ -626,18 +668,23 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
626
668
  decorators = [dec['id'] for dec in function_def['decorator_list'] if 'id' in dec] # ignores Call decorators
627
669
 
628
670
  result = []
671
+ is_constructor = function_def['name'] == CompilerLangVy.vyper_constructor_name
629
672
  for args in arg_variants:
630
673
  arg_names, arg_types = [n for n, t in args], [t for n, t in args] # python's not smart enough to type `zip`
674
+ if not is_constructor:
675
+ func_selector = CompilerLangVy.get_function_selector(function_def['name'], arg_types, is_lib=False)
676
+ else:
677
+ func_selector = "0" # this is the sighash for constructors in Solidity too
631
678
  result.append(CompilerLangFunc(
632
679
  name = function_def['name'],
633
- fullargs = arg_types,
634
- paramnames = arg_names,
680
+ fullArgs = arg_types,
681
+ paramNames = arg_names,
635
682
  returns = ret_types,
636
- sighash = CompilerLangVy.get_function_selector(function_def['name'], arg_types, is_lib=False),
683
+ sighash = func_selector,
637
684
  notpayable = "payable" not in decorators,
638
- fromlib = False,
639
- isconstructor = function_def['name'] == "__init__",
640
- statemutability = first_of(decorators, ["pure", "view", "payable"], default="nonpayable"),
685
+ fromLib = False,
686
+ isConstructor = is_constructor,
687
+ stateMutability = first_of(decorators, ["pure", "view", "payable"], default="nonpayable"),
641
688
  implemented = True,
642
689
  overrides = False,
643
690
  visibility = first_of(decorators, ["internal", "external"]),
@@ -656,14 +703,14 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
656
703
 
657
704
  return CompilerLangFunc(
658
705
  name = var_name,
659
- fullargs = arg_types,
660
- paramnames = [],
706
+ fullArgs = arg_types,
707
+ paramNames = [],
661
708
  returns = ret_types,
662
709
  sighash = CompilerLangVy.get_function_selector(var_name, arg_types, is_lib=False),
663
710
  notpayable = True,
664
- fromlib = False,
665
- isconstructor = False,
666
- statemutability = "view",
711
+ fromLib = False,
712
+ isConstructor = False,
713
+ stateMutability = "view",
667
714
  implemented = True,
668
715
  overrides = False,
669
716
  visibility = "external",
@@ -699,15 +746,22 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
699
746
  result_types = []
700
747
  public_vardecls = {}
701
748
  named_constants: Dict[str, int] = {}
749
+
750
+ # Process named constants ahead of time, as their use site in the source may precede
751
+ # their definition site, e.g.
752
+ for ast_node in ast_body_nodes.values():
753
+ if ast_node['ast_type'] != 'VariableDecl':
754
+ continue
755
+ if ast_node['is_constant'] and ast_node['value'] is not None and \
756
+ (ast_node['value']['ast_type'] == 'Int'):
757
+ named_constants.update({ast_node['target']['id']: int(ast_node['value']['value'])})
758
+
702
759
  for ast_node in ast_body_nodes.values():
703
760
  if ast_node['ast_type'] == 'VariableDecl':
704
761
  decltype = CompilerLangVy.extract_type_from_variable_decl(ast_node, named_constants)
705
762
  result_types.append(decltype)
706
763
  if ast_node['is_public']:
707
764
  public_vardecls[ast_node['target']['id']] = decltype
708
- if ast_node['is_constant'] and (ast_node['value'] is not None) and \
709
- (ast_node['value']['ast_type'] == 'Int'):
710
- named_constants.update({ast_node['target']['id']: int(ast_node['value']['value'])})
711
765
  elif ast_node['ast_type'] == 'StructDef':
712
766
  result_types.append(CompilerLangVy.extract_type_from_struct_def(ast_node, named_constants))
713
767
  # Not sure if `Import` is an actual ast type. It was already there, so I am not removing it.
@@ -791,7 +845,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
791
845
  list(CompilerLangVy.primitive_types.values())
792
846
  type_descriptors_by_name = {i.get_canonical_vyper_name(): i.get_storage_type_descriptor()
793
847
  for i in all_used_types}
794
- types_field = {i.get_canonical_vyper_name(): i.generate_types_field() for i in all_used_types}
848
+ types_field = {i.get_canonical_vyper_name(): i.generate_types_field(storage=True) for i in all_used_types}
795
849
 
796
850
  def annotate_desc(desc: Dict[Any, Any], type_name: str, all_types: Dict[Any, Any], slot: Any = None,
797
851
  offset: Any = None) -> Dict[Any, Any]:
@@ -968,20 +1022,24 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
968
1022
  solidity_type_args = [get_solidity_type_from_abi(p) for p in params]
969
1023
  solidity_type_outs = [get_solidity_type_from_abi(p) for p in out_params]
970
1024
 
971
- func_selector = get_function_selector({}, name, solidity_type_args, True)
1025
+ is_constructor = name == CompilerLangVy.vyper_constructor_name
1026
+ if not is_constructor:
1027
+ func_selector = get_function_selector({}, name, solidity_type_args, True)
1028
+ else:
1029
+ func_selector = "0" # this is the sighash for constructors in Solidity too
972
1030
  state_mutability = abi_data["stateMutability"]
973
1031
 
974
1032
  funcs.append(
975
1033
  CompilerLangFunc(
976
1034
  name=name,
977
- fullargs=solidity_type_args,
978
- paramnames=[],
1035
+ fullArgs=solidity_type_args,
1036
+ paramNames=[],
979
1037
  returns=solidity_type_outs,
980
1038
  sighash=func_selector,
981
1039
  notpayable=state_mutability in ["nonpayable", "view", "pure"],
982
- fromlib=False,
983
- isconstructor=False,
984
- statemutability=state_mutability,
1040
+ fromLib=False,
1041
+ isConstructor=is_constructor,
1042
+ stateMutability=state_mutability,
985
1043
  implemented=True,
986
1044
  overrides=False,
987
1045
  # according to Solidity docs, getter functions have external visibility