certora-cli-beta-mirror 8.6.3__tar.gz → 8.8.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.
- {certora_cli_beta_mirror-8.6.3/certora_cli_beta_mirror.egg-info → certora_cli_beta_mirror-8.8.0}/PKG-INFO +2 -2
- certora_cli_beta_mirror-8.8.0/README.md +1 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollector.py +9 -8
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorVy.py +126 -73
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/castingInstrumenter.py +23 -16
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraBuild.py +111 -34
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraContextAttributes.py +57 -1
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraContextValidator.py +8 -1
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraContractFuncs.py +1 -1
- certora_cli_beta_mirror-8.8.0/certora_cli/CertoraProver/certoraOffsetConverter.py +54 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraSourceFinders.py +7 -7
- certora_cli_beta_mirror-8.8.0/certora_cli/CertoraProver/uncheckedOverflowInstrumenter.py +152 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/certoraValidateFuncs.py +31 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0/certora_cli_beta_mirror.egg-info}/PKG-INFO +2 -2
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli_beta_mirror.egg-info/SOURCES.txt +2 -0
- certora_cli_beta_mirror-8.6.3/certora_jars/Typechecker.jar → certora_cli_beta_mirror-8.8.0/certora_jars/ASTExtraction.jar +0 -0
- certora_cli_beta_mirror-8.8.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- certora_cli_beta_mirror-8.6.3/certora_jars/ASTExtraction.jar → certora_cli_beta_mirror-8.8.0/certora_jars/Typechecker.jar +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/setup.py +2 -2
- certora_cli_beta_mirror-8.6.3/README.md +0 -1
- certora_cli_beta_mirror-8.6.3/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/LICENSE +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/MANIFEST.in +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_bins/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/Compiler/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraApp.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraBuildCacheManager.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraBuildDataClasses.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraBuildRust.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraBuildSui.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraCloudIO.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraCollectConfigurationLayout.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraCollectRunMetadata.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraCompilerParameters.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraConfigIO.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraContext.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraContextClass.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraExtensionInfo.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraJobList.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraMiniSpecParser.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraNodeFilters.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraParseBuildScript.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraProjectScanner.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraType.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/certoraVerifyGenerator.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/erc7201.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/splitRules.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/CertoraProver/storageExtension.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/mutateApp.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/mutateAttributes.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/mutateConstants.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/mutateUtil.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Mutate/mutateValidate.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/certoraAttrUtil.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/certoraUtils.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/Shared/proverCommon.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraCVLFormatter.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraConcord.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraEVMProver.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraMutate.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraRanger.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraRun.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraSolanaProver.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraSorobanProver.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/certoraSuiProver.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli/rustMutator.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli_beta_mirror.egg-info/dependency_links.txt +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli_beta_mirror.egg-info/entry_points.txt +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli_beta_mirror.egg-info/requires.txt +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_cli_beta_mirror.egg-info/top_level.txt +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/certora_jars/__init__.py +0 -0
- {certora_cli_beta_mirror-8.6.3 → certora_cli_beta_mirror-8.8.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: certora-cli-beta-mirror
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.8.0
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli-beta-mirror
|
|
6
6
|
Author: Certora
|
|
@@ -38,4 +38,4 @@ Dynamic: requires-dist
|
|
|
38
38
|
Dynamic: requires-python
|
|
39
39
|
Dynamic: summary
|
|
40
40
|
|
|
41
|
-
Commit
|
|
41
|
+
Commit 2cf089d. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 2cf089d. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -66,13 +66,6 @@ class CompilerLang(metaclass=AbstractAndSingleton):
|
|
|
66
66
|
"""
|
|
67
67
|
return func_hash
|
|
68
68
|
|
|
69
|
-
@staticmethod
|
|
70
|
-
def normalize_file_compiler_path_name(file_abs_path: str) -> str:
|
|
71
|
-
"""
|
|
72
|
-
Normalizes the absolute path name [file_abs_path] of a file, given to the compiler.
|
|
73
|
-
"""
|
|
74
|
-
return file_abs_path
|
|
75
|
-
|
|
76
69
|
@staticmethod
|
|
77
70
|
def normalize_deployed_bytecode(deployed_bytecode: str) -> str:
|
|
78
71
|
"""
|
|
@@ -114,7 +107,9 @@ class CompilerLang(metaclass=AbstractAndSingleton):
|
|
|
114
107
|
config_path: Path,
|
|
115
108
|
compiler_cmd: str,
|
|
116
109
|
compiler_version: Optional[CompilerVersion],
|
|
117
|
-
data: Dict[str, Any]
|
|
110
|
+
data: Dict[str, Any],
|
|
111
|
+
asts : Dict[str, Dict[int, Any]],
|
|
112
|
+
ast_key: str) -> Dict[str, Any]:
|
|
118
113
|
"""
|
|
119
114
|
Returns the data dictionary of the contract with storage layout information if needed
|
|
120
115
|
"""
|
|
@@ -195,5 +190,11 @@ class CompilerCollector(ABC):
|
|
|
195
190
|
def compiler_version(self) -> CompilerVersion:
|
|
196
191
|
pass
|
|
197
192
|
|
|
193
|
+
def normalize_file_compiler_path_name(self, file_abs_path: str) -> str:
|
|
194
|
+
"""
|
|
195
|
+
Normalizes the absolute path name [file_abs_path] of a file, given to the compiler.
|
|
196
|
+
"""
|
|
197
|
+
return file_abs_path
|
|
198
|
+
|
|
198
199
|
def __str__(self) -> str:
|
|
199
200
|
return f"{self.compiler_name} {self.compiler_version}"
|
|
@@ -52,12 +52,6 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
52
52
|
except ValueError:
|
|
53
53
|
raise Exception(f'{func_hash} is not convertible to hexadecimal')
|
|
54
54
|
|
|
55
|
-
@staticmethod
|
|
56
|
-
def normalize_file_compiler_path_name(file_abs_path: str) -> str:
|
|
57
|
-
if not file_abs_path.startswith('/'):
|
|
58
|
-
return '/' + file_abs_path
|
|
59
|
-
return file_abs_path
|
|
60
|
-
|
|
61
55
|
@staticmethod
|
|
62
56
|
def normalize_deployed_bytecode(deployed_bytecode: str) -> str:
|
|
63
57
|
assert deployed_bytecode.startswith("0x"), f'expected {deployed_bytecode} to have hexadecimal prefix'
|
|
@@ -785,10 +779,10 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
785
779
|
return [t.resolve_forward_declared_types(name_resolution_dict) for t in real_types]
|
|
786
780
|
|
|
787
781
|
@staticmethod
|
|
788
|
-
def extract_ast_types_and_public_vardecls(
|
|
782
|
+
def extract_ast_types_and_public_vardecls(ast_body_nodes_per_file: Dict[str, Dict[int, Dict[str, Any]]]) -> \
|
|
789
783
|
Tuple[List[VyperType], Dict[str, VyperType]]:
|
|
790
784
|
"""
|
|
791
|
-
:param
|
|
785
|
+
:param ast_body_nodes_per_file:
|
|
792
786
|
:return: (types, vars) where `types` is a list of all user-defined types, and `vars` maps public variables to
|
|
793
787
|
their output types. Note that `types` has been fully resolved - all `VyperTypeNameReference` nodes have been
|
|
794
788
|
dereferenced
|
|
@@ -805,38 +799,50 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
805
799
|
|
|
806
800
|
# Process named constants ahead of time, as their use site in the source may precede
|
|
807
801
|
# their definition site, e.g.
|
|
808
|
-
for
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
if ast_node['
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
802
|
+
for _, ast_body_nodes in ast_body_nodes_per_file.items():
|
|
803
|
+
for ast_node in ast_body_nodes.values():
|
|
804
|
+
if ast_node['ast_type'] != 'VariableDecl':
|
|
805
|
+
continue
|
|
806
|
+
if ast_node['is_constant'] and ast_node['value'] is not None and \
|
|
807
|
+
(ast_node['value']['ast_type'] == 'Int'):
|
|
808
|
+
named_constants.update({ast_node['target']['id']: int(ast_node['value']['value'])})
|
|
809
|
+
|
|
810
|
+
resolved_result_types = []
|
|
811
|
+
for _, ast_body_nodes in ast_body_nodes_per_file.items():
|
|
812
|
+
for ast_node in ast_body_nodes.values():
|
|
813
|
+
if ast_node['ast_type'] == 'VariableDecl':
|
|
814
|
+
decltype = CompilerLangVy.extract_type_from_variable_decl(ast_node, named_constants)
|
|
815
|
+
result_types.append(decltype)
|
|
816
|
+
if ast_node['is_public']:
|
|
817
|
+
public_vardecls[ast_node['target']['id']] = decltype
|
|
818
|
+
elif ast_node['ast_type'] == 'StructDef':
|
|
819
|
+
result_types.append(CompilerLangVy.extract_type_from_struct_def(ast_node, named_constants))
|
|
820
|
+
# Not sure if `Import` is an actual ast type. It was already there, so I am not removing it.
|
|
821
|
+
# I only fixed the implementation of this case to what I think it should be.
|
|
822
|
+
elif ast_node['ast_type'] in ['Import', 'ImportFrom']:
|
|
823
|
+
if "name" in ast_node:
|
|
824
|
+
result_types.append(CompilerLangVy.VyperTypeContract(ast_node['name']))
|
|
825
|
+
elif "names" in ast_node:
|
|
826
|
+
n_list = ast_node["names"]
|
|
827
|
+
for t in n_list:
|
|
828
|
+
result_types.append(CompilerLangVy.VyperTypeContract(t["name"]))
|
|
829
|
+
else:
|
|
830
|
+
raise Exception("Unrecognized import node")
|
|
831
|
+
elif ast_node['ast_type'] == 'InterfaceDef':
|
|
832
|
+
result_types.append(CompilerLangVy.VyperTypeContract(ast_node['name']))
|
|
833
|
+
resolved_result_types.extend(CompilerLangVy.resolve_extracted_types(result_types))
|
|
834
|
+
|
|
835
|
+
# SG: I'm not sure why we didn't set it as a set to begin with. Punting for now
|
|
836
|
+
return list(set(resolved_result_types)), resolve_vardecl_types(public_vardecls, resolved_result_types)
|
|
833
837
|
|
|
834
838
|
@staticmethod
|
|
835
839
|
def collect_storage_layout_info(file_abs_path: str,
|
|
836
840
|
config_path: Path,
|
|
837
841
|
compiler_cmd: str,
|
|
838
842
|
compiler_version: Optional[CompilerVersion],
|
|
839
|
-
data: Dict[str, Any]
|
|
843
|
+
data: Dict[str, Any],
|
|
844
|
+
asts : Dict[str, Dict[int, Any]],
|
|
845
|
+
ast_key: str) -> Dict[str, Any]:
|
|
840
846
|
# only Vyper versions 0.2.16 and up have the storage layout
|
|
841
847
|
if compiler_version is None or not CompilerCollectorVy.supports_storage_layout(compiler_version):
|
|
842
848
|
return data
|
|
@@ -872,20 +878,6 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
872
878
|
print(f'Error: {e}')
|
|
873
879
|
print_failed_to_run(compiler_cmd)
|
|
874
880
|
raise
|
|
875
|
-
ast_output_file_name = f'{get_certora_config_dir()}.ast'
|
|
876
|
-
ast_stdout_name = storage_layout_output_file_name + '.stdout'
|
|
877
|
-
ast_stderr_name = storage_layout_output_file_name + '.stderr'
|
|
878
|
-
args = [compiler_cmd, '-f', 'ast', '-o', ast_output_file_name, file_abs_path]
|
|
879
|
-
with Path(ast_stdout_name).open('w+') as stdout:
|
|
880
|
-
with Path(ast_stderr_name).open('w+') as stderr:
|
|
881
|
-
try:
|
|
882
|
-
subprocess.run(args, stdout=stdout, stderr=stderr)
|
|
883
|
-
with Path(ast_output_file_name).open('r') as output_file:
|
|
884
|
-
ast_dict = json.load(output_file)
|
|
885
|
-
except Exception as e:
|
|
886
|
-
print(f'Error: {e}')
|
|
887
|
-
print_failed_to_run(compiler_cmd)
|
|
888
|
-
raise
|
|
889
881
|
|
|
890
882
|
# Depressing how many bugs old Vyper had. Example:
|
|
891
883
|
# vyper 0.3.7: "userBalances": {"type": "HashMap[address, uint256]", "slot": 1}
|
|
@@ -893,10 +885,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
893
885
|
# "location": "storage", "slot": 2}
|
|
894
886
|
# so we'll just gracefully exit
|
|
895
887
|
try:
|
|
896
|
-
|
|
897
|
-
extracted_types, _ = CompilerLangVy.extract_ast_types_and_public_vardecls(
|
|
898
|
-
{x['node_id']: x for x in ast_dict['ast']['body']}
|
|
899
|
-
)
|
|
888
|
+
extracted_types, _ = CompilerLangVy.extract_ast_types_and_public_vardecls(asts)
|
|
900
889
|
all_used_types = list(itertools.chain.from_iterable([e.get_used_types() for e in extracted_types])) + \
|
|
901
890
|
list(CompilerLangVy.primitive_types.values())
|
|
902
891
|
type_descriptors_by_name = {i.get_canonical_vyper_name(): i.get_storage_type_descriptor()
|
|
@@ -931,22 +920,63 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
931
920
|
|
|
932
921
|
return desc
|
|
933
922
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
'
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
923
|
+
def extract_storage_fields(storage_layout_dict: Dict[str, Any],
|
|
924
|
+
type_descriptors_by_name: Dict[str, Dict[str, Any]],
|
|
925
|
+
types_field: Dict[str, Dict[str, Any]],
|
|
926
|
+
parent_path: str = "") -> List[Dict[str, Any]]:
|
|
927
|
+
"""
|
|
928
|
+
Recursively traverse storage layout dictionary and extract all fields with 'slot' keys.
|
|
929
|
+
|
|
930
|
+
Args:
|
|
931
|
+
storage_layout_dict: The storage layout dictionary to traverse
|
|
932
|
+
type_descriptors_by_name: Type descriptors mapping
|
|
933
|
+
types_field: Types field for annotation
|
|
934
|
+
parent_path: Current path in the hierarchy (for building field labels)
|
|
935
|
+
|
|
936
|
+
Returns:
|
|
937
|
+
List of storage field dictionaries
|
|
938
|
+
"""
|
|
939
|
+
storage_fields = []
|
|
940
|
+
|
|
941
|
+
for key, value in storage_layout_dict.items():
|
|
942
|
+
current_path = f"{parent_path}.{key}" if parent_path else key
|
|
943
|
+
|
|
944
|
+
if isinstance(value, dict):
|
|
945
|
+
# Check if this dict contains a 'slot' key (leaf node)
|
|
946
|
+
if 'slot' in value:
|
|
947
|
+
# This is a storage variable - process it
|
|
948
|
+
storage_fields.append({
|
|
949
|
+
'label': current_path,
|
|
950
|
+
'slot': str(value['slot']),
|
|
951
|
+
'offset': 0,
|
|
952
|
+
'type': value['type'],
|
|
953
|
+
'descriptor': annotate_desc(
|
|
954
|
+
type_descriptors_by_name[value['type']],
|
|
955
|
+
value['type'],
|
|
956
|
+
types_field
|
|
957
|
+
)
|
|
958
|
+
})
|
|
959
|
+
else:
|
|
960
|
+
# This is a nested structure - recurse into it
|
|
961
|
+
storage_fields.extend(
|
|
962
|
+
extract_storage_fields(value, type_descriptors_by_name, types_field, current_path)
|
|
963
|
+
)
|
|
964
|
+
|
|
965
|
+
return storage_fields
|
|
966
|
+
|
|
967
|
+
storage_field = extract_storage_fields(storage_layout_dict, type_descriptors_by_name, types_field)
|
|
968
|
+
|
|
969
|
+
data_key = file_abs_path if file_abs_path in data["contracts"] else ast_key
|
|
970
|
+
if data_key not in data["contracts"]:
|
|
971
|
+
raise Exception(f"Expected to have the right key into the json out for updating the storage layout, "
|
|
972
|
+
f"tried {file_abs_path} and {ast_key} but keys are {data['contracts'].keys()}")
|
|
973
|
+
contract_name = list(data['contracts'][data_key].keys())[0]
|
|
974
|
+
data['contracts'][data_key][contract_name]['storageLayout'] = {
|
|
945
975
|
'storage': storage_field,
|
|
946
976
|
'types': types_field,
|
|
947
977
|
'storageHashArgsReversed': True
|
|
948
978
|
}
|
|
949
|
-
data['contracts'][
|
|
979
|
+
data['contracts'][data_key][contract_name]['storageHashArgsReversed'] = True
|
|
950
980
|
return data
|
|
951
981
|
except Exception as e:
|
|
952
982
|
ast_logger.warning(f'Failed to get storage layout, continuing: {e}')
|
|
@@ -1175,7 +1205,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
1175
1205
|
return funcs
|
|
1176
1206
|
|
|
1177
1207
|
vyper_types, public_vardecls = \
|
|
1178
|
-
CompilerLangVy.extract_ast_types_and_public_vardecls(asts[build_arg_contract_file]
|
|
1208
|
+
CompilerLangVy.extract_ast_types_and_public_vardecls(asts[build_arg_contract_file])
|
|
1179
1209
|
ct_types = [x.get_certora_type(contract_name, 0) for x in vyper_types]
|
|
1180
1210
|
getter_vars_list = [(v, public_vardecls[v].get_certora_type(contract_name, 0))
|
|
1181
1211
|
for v in public_vardecls if isinstance(public_vardecls[v], CompilerLangVy.VyperTypeHashMap)]
|
|
@@ -1208,7 +1238,7 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
1208
1238
|
|
|
1209
1239
|
try:
|
|
1210
1240
|
# TODO: verify that the collected functions matches the information in data['abi']
|
|
1211
|
-
collector = Collector(contract_name, asts[build_arg_contract_file]
|
|
1241
|
+
collector = Collector(contract_name, asts[build_arg_contract_file])
|
|
1212
1242
|
type_descriptions_and_funcs = [t.get_certora_type(contract_name, 0) for t in
|
|
1213
1243
|
collector.types.values()], collector.funcs
|
|
1214
1244
|
|
|
@@ -1249,17 +1279,24 @@ class Collector:
|
|
|
1249
1279
|
|
|
1250
1280
|
_contract_name : str
|
|
1251
1281
|
|
|
1252
|
-
def __init__(self, contract_name : str,
|
|
1282
|
+
def __init__(self, contract_name : str, asts_per_file: Dict[str, Dict[int, Dict[str, Any]]]):
|
|
1253
1283
|
"""Collect the types and functions from the top-level 'AST' node in [ast]."""
|
|
1254
1284
|
self.types = {}
|
|
1255
1285
|
self.funcs = []
|
|
1256
1286
|
self.consts = {}
|
|
1257
1287
|
self._contract_name = contract_name
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1288
|
+
# first pass - get all constants
|
|
1289
|
+
for _, asts in asts_per_file.items():
|
|
1290
|
+
for node in asts.values():
|
|
1291
|
+
if node['ast_type'] == 'Module':
|
|
1292
|
+
self._collect_module_consts(node)
|
|
1293
|
+
|
|
1294
|
+
for _, asts in asts_per_file.items():
|
|
1295
|
+
for node in asts.values():
|
|
1296
|
+
if node['ast_type'] == 'Module':
|
|
1297
|
+
self._collect_module(node)
|
|
1298
|
+
|
|
1299
|
+
def _collect_module_consts(self, module_node: Dict[str, Any]) -> None:
|
|
1263
1300
|
"""Populate [self.types] and [self.funcs] base on 'Module' AST node in [node]."""
|
|
1264
1301
|
assert module_node['ast_type'] == "Module"
|
|
1265
1302
|
|
|
@@ -1272,6 +1309,7 @@ class Collector:
|
|
|
1272
1309
|
for v in var_decls:
|
|
1273
1310
|
self._collect_const(v)
|
|
1274
1311
|
|
|
1312
|
+
def _collect_module(self, module_node: Dict[str, Any]) -> None:
|
|
1275
1313
|
# Extract and resolve types
|
|
1276
1314
|
type_asts = {'EnumDef', 'StructDef', 'InterfaceDef', 'Import', 'Import', 'ImportFrom', 'FlagDef'}
|
|
1277
1315
|
types = [e for e in module_node['body'] if e['ast_type'] in type_asts]
|
|
@@ -1286,6 +1324,7 @@ class Collector:
|
|
|
1286
1324
|
for f in funs:
|
|
1287
1325
|
self._collect_func(f)
|
|
1288
1326
|
|
|
1327
|
+
var_decls = [e for e in module_node['body'] if e['ast_type'] == 'VariableDecl']
|
|
1289
1328
|
# Add getters for public variables (also needs to happen after type resolution)
|
|
1290
1329
|
for v in var_decls:
|
|
1291
1330
|
self._collect_getter(v)
|
|
@@ -1308,7 +1347,16 @@ class Collector:
|
|
|
1308
1347
|
# TODO: this is probably wrong, since you can probably import constants and things too...
|
|
1309
1348
|
# although in practice it appears that people only import constants
|
|
1310
1349
|
elif type_decl_node['ast_type'] in ('InterfaceDef', 'Import', 'ImportFrom'):
|
|
1311
|
-
|
|
1350
|
+
if "names" in type_decl_node:
|
|
1351
|
+
n_list = type_decl_node["names"]
|
|
1352
|
+
for t in n_list:
|
|
1353
|
+
ty = CompilerLangVy.VyperTypeContract(t["name"])
|
|
1354
|
+
self.types[t["name"]] = ty
|
|
1355
|
+
return
|
|
1356
|
+
elif "name" in type_decl_node:
|
|
1357
|
+
vy_type = CompilerLangVy.VyperTypeContract(type_decl_node['name'])
|
|
1358
|
+
else:
|
|
1359
|
+
raise AssertionError("Unexpected type definition")
|
|
1312
1360
|
else:
|
|
1313
1361
|
raise AssertionError("Unexpected type definition")
|
|
1314
1362
|
self.types[type_decl_node['name']] = vy_type
|
|
@@ -1386,6 +1434,11 @@ class CompilerCollectorVy(CompilerCollector):
|
|
|
1386
1434
|
def compiler_version(self) -> CompilerVersion:
|
|
1387
1435
|
return self.__compiler_version
|
|
1388
1436
|
|
|
1437
|
+
def normalize_file_compiler_path_name(self, file_abs_path: str) -> str:
|
|
1438
|
+
if self.compiler_version[1] < 4 and not file_abs_path.startswith('/'):
|
|
1439
|
+
return '/' + file_abs_path
|
|
1440
|
+
return file_abs_path
|
|
1441
|
+
|
|
1389
1442
|
@staticmethod
|
|
1390
1443
|
def supports_storage_layout(version: CompilerVersion) -> bool:
|
|
1391
1444
|
return (version[1] > 2 or (
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
from dataclasses import dataclass
|
|
18
|
-
from typing import Dict, Any, Optional, Generator
|
|
18
|
+
from typing import Dict, Any, Optional, Callable, Generator
|
|
19
19
|
|
|
20
20
|
from CertoraProver.Compiler.CompilerCollectorSol import CompilerCollectorSol
|
|
21
21
|
from CertoraProver.certoraBuildDataClasses import SDC, Instrumentation, Replace
|
|
22
|
+
from CertoraProver.certoraOffsetConverter import OffsetConverter
|
|
22
23
|
from Shared import certoraUtils as Util
|
|
23
24
|
|
|
24
25
|
|
|
@@ -92,7 +93,7 @@ def find_casts(ast: Dict[int, Any]) -> list[CastInfo]:
|
|
|
92
93
|
function_nodes = [node for node in ast.values() if node.get('nodeType') == 'FunctionDefinition']
|
|
93
94
|
|
|
94
95
|
for func in function_nodes:
|
|
95
|
-
for node in
|
|
96
|
+
for node in iter_all_nodes_under(func):
|
|
96
97
|
if isinstance(node, dict) and node.get("kind") == "typeConversion":
|
|
97
98
|
arguments = node.get("arguments", [])
|
|
98
99
|
if len(arguments) == 1 and isinstance(arguments[0], dict):
|
|
@@ -119,19 +120,21 @@ def casting_func_name(counter: int) -> str:
|
|
|
119
120
|
return f"cast_{counter}"
|
|
120
121
|
|
|
121
122
|
|
|
122
|
-
def generate_casting_function(assembly_prefix: str, cast_info: CastInfo, counter: int) -> str:
|
|
123
|
+
def generate_casting_function(assembly_prefix: str, cast_info: CastInfo, counter: int, line: int, column: int) -> str:
|
|
123
124
|
"""
|
|
124
125
|
returns the text of a solidity function that does casting according to CastInfo. It also has an encoded mload
|
|
125
126
|
call, to be decoded later on the kotlin side if we run the `safeCasting` builtin rule.
|
|
126
127
|
"""
|
|
127
|
-
conversion_string = assembly_prefix +
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
conversion_string = (assembly_prefix +
|
|
129
|
+
"{ mstore(0xffffff6e4604afefe123321beef1b03fffffffffffffff" +
|
|
130
|
+
f'{"%0.5x" % line}{"%0.5x" % column}{"%0.4x" % encode_type(cast_info.arg_type_str)}{"%0.4x" % encode_type(cast_info.res_type_str)}, x)'
|
|
131
|
+
"}")
|
|
130
132
|
function_head = f"function {casting_func_name(counter)}({cast_info.arg_type_str} x) internal pure returns ({cast_info.res_type_str})"
|
|
131
133
|
return function_head + "{\n" + conversion_string + f"return {cast_info.res_type_str}(x);\n" "}\n"
|
|
132
134
|
|
|
133
135
|
|
|
134
|
-
def generate_casting_instrumentation(asts: Dict[str, Dict[str, Dict[int, Any]]], contract_file: str, sdc: SDC
|
|
136
|
+
def generate_casting_instrumentation(asts: Dict[str, Dict[str, Dict[int, Any]]], contract_file: str, sdc: SDC,
|
|
137
|
+
offset_converters: dict[str, OffsetConverter]) \
|
|
135
138
|
-> tuple[Dict[str, Dict[int, Instrumentation]], Dict[str, tuple[str, list[str]]]]:
|
|
136
139
|
"""
|
|
137
140
|
Generate instrumentation for integer type casts in Solidity code.
|
|
@@ -152,7 +155,7 @@ def generate_casting_instrumentation(asts: Dict[str, Dict[str, Dict[int, Any]]],
|
|
|
152
155
|
" when trying to add casting instrumentation")
|
|
153
156
|
assembly_prefix = sdc.compiler_collector.gen_memory_safe_assembly_prefix()
|
|
154
157
|
|
|
155
|
-
casting_funcs
|
|
158
|
+
casting_funcs: dict[str, tuple[str, list[str]]] = dict()
|
|
156
159
|
counter = 0
|
|
157
160
|
original_files = sorted({Util.convert_path_for_solc_import(c.original_file) for c in sdc.contracts})
|
|
158
161
|
for file_count, solfile in enumerate(original_files, start=1):
|
|
@@ -165,28 +168,32 @@ def generate_casting_instrumentation(asts: Dict[str, Dict[str, Dict[int, Any]]],
|
|
|
165
168
|
casts = find_casts(curr_file_ast)
|
|
166
169
|
for cast_info in casts:
|
|
167
170
|
start_offset, src_len, file = curr_file_ast[cast_info.expr_id]["src"].split(":")
|
|
171
|
+
line, column = offset_converters[solfile].offset_to_line_column(int(start_offset))
|
|
168
172
|
counter += 1
|
|
169
173
|
per_file_inst[int(start_offset)] = Instrumentation(expected=bytes(cast_info.res_type_str[0], 'utf-8'),
|
|
170
174
|
to_ins=f"{libname}.{casting_func_name(counter)}",
|
|
171
175
|
mut=Replace(len(cast_info.res_type_str)))
|
|
172
|
-
new_func = generate_casting_function(assembly_prefix, cast_info, counter)
|
|
176
|
+
new_func = generate_casting_function(assembly_prefix, cast_info, counter, line, column)
|
|
173
177
|
per_file_casts.append(new_func)
|
|
174
178
|
|
|
175
179
|
return casting_instrumentation, casting_funcs
|
|
176
180
|
|
|
177
181
|
|
|
178
|
-
def
|
|
182
|
+
def iter_all_nodes_under(node: Any, f: Callable[[Any], bool] = lambda node: True, is_inside: bool = False) \
|
|
183
|
+
-> Generator[Any, Optional[Any], None]:
|
|
179
184
|
"""
|
|
180
|
-
Yield a node and all its subnodes in depth-first order.
|
|
185
|
+
Yield a node and all its subnodes in depth-first order, but only recursively under nodes where f returns True.
|
|
181
186
|
Works with dict nodes that may contain nested dicts and lists.
|
|
182
187
|
"""
|
|
183
|
-
|
|
188
|
+
inside = is_inside
|
|
189
|
+
if f(node):
|
|
190
|
+
inside = True
|
|
191
|
+
if inside:
|
|
192
|
+
yield node
|
|
184
193
|
|
|
185
194
|
if isinstance(node, dict):
|
|
186
195
|
for value in node.values():
|
|
187
|
-
|
|
188
|
-
yield from iter_all_nodes(value)
|
|
196
|
+
yield from iter_all_nodes_under(value, f, inside)
|
|
189
197
|
elif isinstance(node, list):
|
|
190
198
|
for item in node:
|
|
191
|
-
|
|
192
|
-
yield from iter_all_nodes(item)
|
|
199
|
+
yield from iter_all_nodes_under(item, f, inside)
|