certora-cli 7.14.3__tar.gz → 7.17.2__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-7.14.3/certora_cli.egg-info → certora_cli-7.17.2}/PKG-INFO +2 -2
- certora_cli-7.17.2/README.md +1 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraBuild.py +176 -56
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraConfigIO.py +1 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContext.py +6 -36
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContextAttributes.py +46 -14
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContextValidator.py +61 -194
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/mutateApp.py +220 -335
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/mutateAttributes.py +0 -1
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/mutateConstants.py +1 -1
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/mutateValidate.py +0 -2
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/certoraUtils.py +1 -1
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/certoraValidateFuncs.py +39 -4
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/certoraMutate.py +8 -5
- {certora_cli-7.14.3 → certora_cli-7.17.2/certora_cli.egg-info}/PKG-INFO +2 -2
- certora_cli-7.17.2/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_jars/Typechecker.jar +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/setup.py +2 -2
- certora_cli-7.14.3/README.md +0 -1
- certora_cli-7.14.3/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli-7.14.3 → certora_cli-7.17.2}/LICENSE +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/MANIFEST.in +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_bins/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraBuildCacheManager.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraCloudIO.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraCompilerParameters.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContractFuncs.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraMiniSpecParser.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraType.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraVerifyGenerator.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Mutate/mutateUtil.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/certoraAttrUtil.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/certoraRun.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli.egg-info/SOURCES.txt +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli.egg-info/entry_points.txt +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli.egg-info/requires.txt +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli.egg-info/top_level.txt +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/certora_jars/__init__.py +0 -0
- {certora_cli-7.14.3 → certora_cli-7.17.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.17.2
|
|
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
|
|
24
|
+
Commit 501a551. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 501a551. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -7,6 +7,7 @@ import shutil
|
|
|
7
7
|
import sys
|
|
8
8
|
import typing
|
|
9
9
|
from collections import OrderedDict
|
|
10
|
+
from dataclasses import dataclass
|
|
10
11
|
from enum import Enum
|
|
11
12
|
from functools import lru_cache
|
|
12
13
|
from pathlib import Path
|
|
@@ -50,6 +51,8 @@ OUTPUTS = "outputs"
|
|
|
50
51
|
FUNCTION = "function"
|
|
51
52
|
CONTRACTS = "contracts"
|
|
52
53
|
NAME = "name"
|
|
54
|
+
MANUAL_MUTANTS = "manual_mutants"
|
|
55
|
+
MUTANTS_LOCATION = "mutants_location"
|
|
53
56
|
|
|
54
57
|
FunctionSig = Tuple[str, List[str], List[str], str]
|
|
55
58
|
|
|
@@ -238,6 +241,18 @@ class PresetImmutableReference(ImmutableReference):
|
|
|
238
241
|
return repr(self.as_dict())
|
|
239
242
|
|
|
240
243
|
|
|
244
|
+
@dataclass
|
|
245
|
+
class ContractExtension:
|
|
246
|
+
extension: "ContractInSDC"
|
|
247
|
+
exclusion: List[str]
|
|
248
|
+
|
|
249
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
250
|
+
return {
|
|
251
|
+
"extension": self.extension.as_dict(),
|
|
252
|
+
"exclusion": self.exclusion
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
241
256
|
# Python3.5 to which we maintain backward-compatibility due to CI's docker image, does not support @dataclass
|
|
242
257
|
class ContractInSDC:
|
|
243
258
|
def __init__(self, name: str, source_file: str, lang: str,
|
|
@@ -246,13 +261,15 @@ class ContractInSDC:
|
|
|
246
261
|
methods: Set[Func], bytecode: str,
|
|
247
262
|
constructor_bytecode: str,
|
|
248
263
|
srcmap: str, varmap: Any, constructor_srcmap: str,
|
|
249
|
-
|
|
264
|
+
storage_layout: Any, transient_storage_layout: Any,
|
|
265
|
+
immutables: List[ImmutableReference],
|
|
250
266
|
function_finders: Dict[str, InternalFunc], internal_funcs: Set[Func], public_funcs: Set[Func],
|
|
251
267
|
all_funcs: List[Func],
|
|
252
268
|
types: List[CT.Type],
|
|
253
269
|
compiler_collector: Optional[CompilerCollector],
|
|
254
270
|
source_bytes: Optional[SourceBytes],
|
|
255
271
|
compiler_parameters: Optional[CompilerParameters],
|
|
272
|
+
extension_contracts: List[ContractExtension]
|
|
256
273
|
):
|
|
257
274
|
self.name = name
|
|
258
275
|
self.original_file = source_file
|
|
@@ -266,7 +283,8 @@ class ContractInSDC:
|
|
|
266
283
|
self.srcmap = srcmap
|
|
267
284
|
self.varmap = varmap
|
|
268
285
|
self.constructorSrcmap = constructor_srcmap
|
|
269
|
-
self.
|
|
286
|
+
self.storage_layout = storage_layout
|
|
287
|
+
self.transient_storage_layout = transient_storage_layout
|
|
270
288
|
self.immutables = immutables
|
|
271
289
|
# function finder: a mapping from external function ids to
|
|
272
290
|
# the ids of the internal functions they are "finding" for us
|
|
@@ -301,6 +319,7 @@ class ContractInSDC:
|
|
|
301
319
|
else:
|
|
302
320
|
compiler_version = "unknown"
|
|
303
321
|
self.compiler_version = compiler_version
|
|
322
|
+
self.extension_contracts = extension_contracts
|
|
304
323
|
|
|
305
324
|
def as_dict(self) -> Dict[str, Any]:
|
|
306
325
|
"""
|
|
@@ -319,7 +338,8 @@ class ContractInSDC:
|
|
|
319
338
|
"srcmap": self.srcmap,
|
|
320
339
|
"varmap": self.varmap,
|
|
321
340
|
"constructorSrcmap": self.constructorSrcmap,
|
|
322
|
-
"storageLayout": self.
|
|
341
|
+
"storageLayout": self.storage_layout,
|
|
342
|
+
"transientStorageLayout": self.transient_storage_layout,
|
|
323
343
|
"immutables": list(map(lambda x: x.as_dict(), self.immutables)),
|
|
324
344
|
# the function finder field
|
|
325
345
|
# why are we using this and not the normal list of functions?
|
|
@@ -331,6 +351,7 @@ class ContractInSDC:
|
|
|
331
351
|
"compilerVersion": self.compiler_version,
|
|
332
352
|
"compilerParameters": None if not self.compiler_parameters else self.compiler_parameters.as_dict(),
|
|
333
353
|
"sourceBytes": None if self.source_bytes is None else self.source_bytes.as_dict(),
|
|
354
|
+
"extensionContracts": [e.as_dict() for e in self.extension_contracts]
|
|
334
355
|
}
|
|
335
356
|
|
|
336
357
|
def as_printable_dict(self) -> Dict[str, Any]:
|
|
@@ -345,7 +366,8 @@ class ContractInSDC:
|
|
|
345
366
|
"file": self.report_source_file,
|
|
346
367
|
"address": self.address,
|
|
347
368
|
"methods": list(map(lambda x: x.as_dict(), self.methods)),
|
|
348
|
-
"storageLayout": self.
|
|
369
|
+
"storageLayout": self.storage_layout,
|
|
370
|
+
"transientStorageLayout": self.transient_storage_layout,
|
|
349
371
|
"immutables": list(map(lambda x: x.as_dict(), self.immutables)),
|
|
350
372
|
"internalFunctions": {k: method.as_dict() for k, method in self.function_finders.items()}
|
|
351
373
|
}
|
|
@@ -359,6 +381,9 @@ class ContractInSDC:
|
|
|
359
381
|
def __repr__(self) -> str:
|
|
360
382
|
return repr(self.as_printable_dict())
|
|
361
383
|
|
|
384
|
+
def add_extension(self, extension: ContractExtension) -> None:
|
|
385
|
+
self.extension_contracts.append(extension)
|
|
386
|
+
|
|
362
387
|
|
|
363
388
|
class SDC:
|
|
364
389
|
"""
|
|
@@ -413,6 +438,7 @@ class SDC:
|
|
|
413
438
|
return contract
|
|
414
439
|
return None
|
|
415
440
|
|
|
441
|
+
|
|
416
442
|
# this function is Solidity specific.
|
|
417
443
|
# todo: create certoraBuildUtilsSol.py file, where such solidity specific functions will be.
|
|
418
444
|
def generate_finder_body(f: Func, internal_id: int, sym: int, compiler_collector: CompilerCollectorSol,
|
|
@@ -562,7 +588,7 @@ def reprint_ast_type(node: Dict[str, Any]) -> Optional[str]:
|
|
|
562
588
|
if "length" in node:
|
|
563
589
|
lnode = node["length"]
|
|
564
590
|
if type(lnode) is not dict or "nodeType" not in lnode or lnode["nodeType"] != "Literal" or \
|
|
565
|
-
|
|
591
|
+
"value" not in lnode:
|
|
566
592
|
return None
|
|
567
593
|
len_str = lnode["value"]
|
|
568
594
|
else:
|
|
@@ -573,7 +599,7 @@ def reprint_ast_type(node: Dict[str, Any]) -> Optional[str]:
|
|
|
573
599
|
return None
|
|
574
600
|
p_node = node["pathNode"]
|
|
575
601
|
if type(p_node) is not dict or "nodeType" not in p_node or \
|
|
576
|
-
|
|
602
|
+
p_node["nodeType"] != "IdentifierPath" or "name" not in p_node:
|
|
577
603
|
return None
|
|
578
604
|
return p_node["name"]
|
|
579
605
|
else:
|
|
@@ -595,7 +621,7 @@ def get_modifier_param_type_name(ind: int, def_node: Dict[str, Any], f: Func) ->
|
|
|
595
621
|
return fallback
|
|
596
622
|
param_def_node = params[ind]
|
|
597
623
|
if type(param_def_node) is not dict or param_def_node["nodeType"] != "VariableDeclaration" or \
|
|
598
|
-
|
|
624
|
+
"typeName" not in param_def_node:
|
|
599
625
|
return fallback
|
|
600
626
|
param_type_node = param_def_node["typeName"]
|
|
601
627
|
if type(param_type_node) is not dict:
|
|
@@ -1429,6 +1455,10 @@ class CertoraBuildGenerator:
|
|
|
1429
1455
|
@staticmethod
|
|
1430
1456
|
def collect_storage_layout(data: Dict[str, Any]) -> Any:
|
|
1431
1457
|
return data.get("storageLayout", None)
|
|
1458
|
+
|
|
1459
|
+
@staticmethod
|
|
1460
|
+
def collect_transient_storage_layout(data: Dict[str, Any]) -> Any:
|
|
1461
|
+
return data.get('transientStorageLayout', None)
|
|
1432
1462
|
|
|
1433
1463
|
# Cache info - on PackingTest there are 514 hits and 34 misses
|
|
1434
1464
|
@lru_cache(maxsize=128)
|
|
@@ -1579,10 +1609,10 @@ class CertoraBuildGenerator:
|
|
|
1579
1609
|
settings_dict["optimizer"]['runs'] = int(self.context.solc_optimize)
|
|
1580
1610
|
# if we are not disabling finder friendly optimizer specifically, enable it whenever viaIR is also enabled
|
|
1581
1611
|
if not self.context.strict_solc_optimizer and (
|
|
1582
|
-
|
|
1612
|
+
self.context.solc_via_ir or self.context.solc_experimental_via_ir):
|
|
1583
1613
|
# The default optimizer steps (taken from libsolidity/interface/OptimiserSettings.h) but with the
|
|
1584
1614
|
# full inliner step removed
|
|
1585
|
-
|
|
1615
|
+
solc0_8_26_to_0_8_27 = "dhfoDgvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLCTUca[r]LSsTFOtfDnca[r]" + \
|
|
1586
1616
|
"IulcscCTUtx[scCTUt]TOntnfDIuljmul[jul]VcTOculjmul"
|
|
1587
1617
|
solc0_8_13_to_0_8_25 = "dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]T" + \
|
|
1588
1618
|
"peulxa[rul]xa[r]cLgvifCTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
|
|
@@ -1626,9 +1656,9 @@ class CertoraBuildGenerator:
|
|
|
1626
1656
|
yul_optimizer_steps = solc0_8_12
|
|
1627
1657
|
elif minor == 8 and 13 <= patch <= 25:
|
|
1628
1658
|
yul_optimizer_steps = solc0_8_13_to_0_8_25
|
|
1629
|
-
elif minor == 8 and patch
|
|
1630
|
-
yul_optimizer_steps =
|
|
1631
|
-
assert yul_optimizer_steps is not None
|
|
1659
|
+
elif minor == 8 and 26 <= patch <= 27:
|
|
1660
|
+
yul_optimizer_steps = solc0_8_26_to_0_8_27
|
|
1661
|
+
assert yul_optimizer_steps is not None, 'Yul Optimizer steps missing for requested Solidity version. Please contact Certora team.'
|
|
1632
1662
|
|
|
1633
1663
|
yul_optimizer_steps = standard_replacement(yul_optimizer_steps)
|
|
1634
1664
|
|
|
@@ -1708,7 +1738,7 @@ class CertoraBuildGenerator:
|
|
|
1708
1738
|
if compiler_collector_lang == CompilerLangSol() or compiler_collector_lang == CompilerLangYul():
|
|
1709
1739
|
sources_dict = {str(contract_file_posix_abs): {
|
|
1710
1740
|
"urls": [str(contract_file_posix_abs)]}} # type: Dict[str, Dict[str, Any]]
|
|
1711
|
-
output_selection = ["storageLayout", "abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers",
|
|
1741
|
+
output_selection = ["transientStorageLayout", "storageLayout", "abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers",
|
|
1712
1742
|
"evm.assembly"]
|
|
1713
1743
|
ast_selection = ["id", "ast"]
|
|
1714
1744
|
elif compiler_collector_lang == CompilerLangVy():
|
|
@@ -2277,6 +2307,69 @@ class CertoraBuildGenerator:
|
|
|
2277
2307
|
build_logger.warning(msg)
|
|
2278
2308
|
|
|
2279
2309
|
return bytecode
|
|
2310
|
+
|
|
2311
|
+
def annotate_storage(self, storage_data: Dict, build_arg_contract_file: str) -> Dict:
|
|
2312
|
+
'''
|
|
2313
|
+
Summary
|
|
2314
|
+
-------
|
|
2315
|
+
Annotates the storage data dictionary in-place with more information needed by the prover.
|
|
2316
|
+
|
|
2317
|
+
Parameters
|
|
2318
|
+
----------
|
|
2319
|
+
storage_data : Dict
|
|
2320
|
+
The dictionary holding the storage data.
|
|
2321
|
+
|
|
2322
|
+
Returns
|
|
2323
|
+
-------
|
|
2324
|
+
Dict
|
|
2325
|
+
A reference to the modified storage_data
|
|
2326
|
+
'''
|
|
2327
|
+
def annotate_type(desc: CT.Type, type_name: str, store_types: Dict[str, Any],
|
|
2328
|
+
slot: Any = None, offset: Any = None) -> None:
|
|
2329
|
+
number_of_bytes = store_types[type_name]['numberOfBytes']
|
|
2330
|
+
lower_bound = store_types[type_name].get('lowerBound')
|
|
2331
|
+
upper_bound = store_types[type_name].get('upperBound')
|
|
2332
|
+
annotations = [CT.StorageAnnotation(number_of_bytes, slot, offset, lower_bound,
|
|
2333
|
+
upper_bound)]
|
|
2334
|
+
desc.annotate(annotations)
|
|
2335
|
+
|
|
2336
|
+
if isinstance(desc, CT.StructType):
|
|
2337
|
+
for desc_member in desc.members:
|
|
2338
|
+
for struct_member in store_types[type_name]['members']:
|
|
2339
|
+
if desc_member.name == struct_member['label']:
|
|
2340
|
+
annotate_type(desc_member.type, struct_member['type'], store_types,
|
|
2341
|
+
struct_member['slot'], struct_member['offset'])
|
|
2342
|
+
if isinstance(desc, CT.MappingType):
|
|
2343
|
+
annotate_type(desc.domain, store_types[type_name]['key'], store_types)
|
|
2344
|
+
annotate_type(desc.codomain, store_types[type_name]['value'], store_types)
|
|
2345
|
+
if isinstance(desc, CT.ArrayType):
|
|
2346
|
+
annotate_type(desc.elementType, store_types[type_name]['base'], store_types)
|
|
2347
|
+
|
|
2348
|
+
if storage_data is None or not isinstance(storage_data, dict) or 'storage' not in storage_data:
|
|
2349
|
+
return storage_data
|
|
2350
|
+
|
|
2351
|
+
declarations = storage_data['storage']
|
|
2352
|
+
if not isinstance(declarations, list):
|
|
2353
|
+
return storage_data
|
|
2354
|
+
|
|
2355
|
+
for storage_slot in declarations:
|
|
2356
|
+
if not isinstance(storage_slot, dict) or not isinstance(storage_slot.get('astId', None), int):
|
|
2357
|
+
continue
|
|
2358
|
+
|
|
2359
|
+
ast_id = storage_slot['astId']
|
|
2360
|
+
node = self.get_node_from_asts(self.asts, build_arg_contract_file, ast_id)
|
|
2361
|
+
if not isinstance(node, dict) or 'typeName' not in node:
|
|
2362
|
+
continue
|
|
2363
|
+
|
|
2364
|
+
descriptor = CT.Type.from_type_name_node(
|
|
2365
|
+
lambda ref: self.get_original_def_node(build_arg_contract_file, ref),
|
|
2366
|
+
lambda ref: self.get_contract_file_of_non_autofinder(build_arg_contract_file, ref),
|
|
2367
|
+
node['typeName']
|
|
2368
|
+
)
|
|
2369
|
+
type_descriptor = descriptor
|
|
2370
|
+
annotate_type(descriptor, storage_slot['type'], storage_data['types'])
|
|
2371
|
+
storage_slot['descriptor'] = type_descriptor.as_dict()
|
|
2372
|
+
return storage_data
|
|
2280
2373
|
|
|
2281
2374
|
def get_contract_in_sdc(self,
|
|
2282
2375
|
source_code_file: str,
|
|
@@ -2319,7 +2412,7 @@ class CertoraBuildGenerator:
|
|
|
2319
2412
|
overrides=x.overrides,
|
|
2320
2413
|
contractName=x.contractName,
|
|
2321
2414
|
ast_id=x.ast_id,
|
|
2322
|
-
source_bytes=
|
|
2415
|
+
source_bytes=x.source_bytes,
|
|
2323
2416
|
original_file=x.original_file,
|
|
2324
2417
|
body_location=x.body_location,
|
|
2325
2418
|
) for x in clfuncs]
|
|
@@ -2364,46 +2457,8 @@ class CertoraBuildGenerator:
|
|
|
2364
2457
|
constructor_bytecode)
|
|
2365
2458
|
address, is_static_address = \
|
|
2366
2459
|
self.find_contract_address(source_code_file, contract_name, contracts_with_chosen_addresses)
|
|
2367
|
-
storage_layout =
|
|
2368
|
-
|
|
2369
|
-
if storage_layout is not None and type(storage_layout) is dict and "storage" in storage_layout:
|
|
2370
|
-
declarations = storage_layout["storage"]
|
|
2371
|
-
if type(declarations) is list:
|
|
2372
|
-
for storage_slot in declarations:
|
|
2373
|
-
if type(storage_slot) is dict and type(storage_slot.get("astId", None)) is int:
|
|
2374
|
-
ast_id = storage_slot["astId"] # type: int
|
|
2375
|
-
node = self.get_node_from_asts(self.asts, build_arg_contract_file, ast_id)
|
|
2376
|
-
if type(node) is dict and "typeName" in node:
|
|
2377
|
-
descriptor = CT.Type.from_type_name_node(
|
|
2378
|
-
lambda ref: self.get_original_def_node(build_arg_contract_file, ref),
|
|
2379
|
-
lambda ref: self.get_contract_file_of_non_autofinder(build_arg_contract_file, ref),
|
|
2380
|
-
node["typeName"]
|
|
2381
|
-
)
|
|
2382
|
-
type_descriptor = descriptor
|
|
2383
|
-
|
|
2384
|
-
def annotate_type(desc: CT.Type, type_name: str, store_types: Dict[str, Any],
|
|
2385
|
-
slot: Any = None, offset: Any = None) -> None:
|
|
2386
|
-
number_of_bytes = store_types[type_name]["numberOfBytes"]
|
|
2387
|
-
lower_bound = store_types[type_name].get("lowerBound")
|
|
2388
|
-
upper_bound = store_types[type_name].get("upperBound")
|
|
2389
|
-
annotations = [CT.StorageAnnotation(number_of_bytes, slot, offset, lower_bound,
|
|
2390
|
-
upper_bound)]
|
|
2391
|
-
desc.annotate(annotations)
|
|
2392
|
-
|
|
2393
|
-
if isinstance(desc, CT.StructType):
|
|
2394
|
-
for desc_member in desc.members:
|
|
2395
|
-
for struct_member in store_types[type_name]["members"]:
|
|
2396
|
-
if desc_member.name == struct_member["label"]:
|
|
2397
|
-
annotate_type(desc_member.type, struct_member["type"], store_types,
|
|
2398
|
-
struct_member["slot"], struct_member["offset"])
|
|
2399
|
-
if isinstance(desc, CT.MappingType):
|
|
2400
|
-
annotate_type(desc.domain, store_types[type_name]["key"], store_types)
|
|
2401
|
-
annotate_type(desc.codomain, store_types[type_name]["value"], store_types)
|
|
2402
|
-
if isinstance(desc, CT.ArrayType):
|
|
2403
|
-
annotate_type(desc.elementType, store_types[type_name]["base"], store_types)
|
|
2404
|
-
|
|
2405
|
-
annotate_type(descriptor, storage_slot["type"], storage_layout["types"])
|
|
2406
|
-
storage_slot["descriptor"] = type_descriptor.as_dict()
|
|
2460
|
+
storage_layout = self.annotate_storage(self.collect_storage_layout(contract_data), build_arg_contract_file)
|
|
2461
|
+
transient_storage_layout = self.annotate_storage(self.collect_transient_storage_layout(contract_data), build_arg_contract_file)
|
|
2407
2462
|
immutables = self.collect_immutables(contract_data, build_arg_contract_file, compiler_lang)
|
|
2408
2463
|
|
|
2409
2464
|
if self.context.internal_funcs is not None:
|
|
@@ -2443,6 +2498,7 @@ class CertoraBuildGenerator:
|
|
|
2443
2498
|
varmap,
|
|
2444
2499
|
constructor_srcmap,
|
|
2445
2500
|
storage_layout,
|
|
2501
|
+
transient_storage_layout,
|
|
2446
2502
|
immutables,
|
|
2447
2503
|
function_finders,
|
|
2448
2504
|
internal_funcs=internal_funcs,
|
|
@@ -2452,6 +2508,7 @@ class CertoraBuildGenerator:
|
|
|
2452
2508
|
compiler_collector=compiler_collector_for_contract_file,
|
|
2453
2509
|
source_bytes=source_bytes,
|
|
2454
2510
|
compiler_parameters=compiler_parameters,
|
|
2511
|
+
extension_contracts=list()
|
|
2455
2512
|
)
|
|
2456
2513
|
|
|
2457
2514
|
@staticmethod
|
|
@@ -2936,6 +2993,7 @@ class CertoraBuildGenerator:
|
|
|
2936
2993
|
|
|
2937
2994
|
self.handle_links()
|
|
2938
2995
|
self.handle_struct_links()
|
|
2996
|
+
self.handle_contract_extensions()
|
|
2939
2997
|
|
|
2940
2998
|
@staticmethod
|
|
2941
2999
|
def get_cwd_rel_in_sources(sources: Set[Path]) -> Tuple[Path, Path]:
|
|
@@ -3250,6 +3308,25 @@ class CertoraBuildGenerator:
|
|
|
3250
3308
|
f"in slot {resolved_src_slot}")
|
|
3251
3309
|
self.SDCs[source_to_update].state[resolved_src_slot] = dst_address
|
|
3252
3310
|
|
|
3311
|
+
def handle_contract_extensions(self):
|
|
3312
|
+
if not self.context.contract_extensions:
|
|
3313
|
+
return
|
|
3314
|
+
|
|
3315
|
+
contracts_by_name = {c.name: c for c in self.get_primary_contracts_from_sdcs()}
|
|
3316
|
+
for extended, extending in self.context.contract_extensions.items():
|
|
3317
|
+
if extended not in contracts_by_name:
|
|
3318
|
+
raise Util.CertoraUserInputError(f"Can't find extended contract {extended} for contract extension")
|
|
3319
|
+
extended_contract = contracts_by_name[extended]
|
|
3320
|
+
for ext in extending:
|
|
3321
|
+
extension = ext["extension"]
|
|
3322
|
+
if extension not in contracts_by_name.keys():
|
|
3323
|
+
raise Util.CertoraUserInputError(f"Can't find extending contract {extension} for contract extension")
|
|
3324
|
+
extension_contract = contracts_by_name[extension]
|
|
3325
|
+
for f in ext["exclude"]:
|
|
3326
|
+
if extension_contract.find_method(f) is None:
|
|
3327
|
+
raise Util.CertoraUserInputError(f"Can't find a method named {f} in contract {extension_contract.name}")
|
|
3328
|
+
extended_contract.add_extension(ContractExtension(extension_contract, ext["exclude"]))
|
|
3329
|
+
|
|
3253
3330
|
def check_if_immutable_is_defined_in_ast(self, reference_to_replace_with_link: str, src_contract: str) -> None:
|
|
3254
3331
|
"""
|
|
3255
3332
|
@param reference_to_replace_with_link: The immutable we could not find in immutable_references
|
|
@@ -3331,6 +3408,11 @@ class CertoraBuildGenerator:
|
|
|
3331
3408
|
def get_matching_sdc_names_from_SDCs(self, contract: str) -> List[str]:
|
|
3332
3409
|
return list(self.__get_matching_sdc_names_for_SDCs_iterator(contract))
|
|
3333
3410
|
|
|
3411
|
+
def get_primary_contracts_from_sdcs(self) -> List[ContractInSDC]:
|
|
3412
|
+
ret = [v.find_contract(v.primary_contract) for v in self.SDCs.values()]
|
|
3413
|
+
assert all(c is not None for c in ret), "failed to find some primary contracts"
|
|
3414
|
+
return ret
|
|
3415
|
+
|
|
3334
3416
|
class SlotResolution(Enum):
|
|
3335
3417
|
SLOT_NO_STORAGE_LAYOUT = enum.auto()
|
|
3336
3418
|
SLOT_INVALID_STORAGE_LAYOUT = enum.auto()
|
|
@@ -3349,8 +3431,8 @@ class CertoraBuildGenerator:
|
|
|
3349
3431
|
string - returns the slot number associated with slot_name as hex without preceding 0x (or 0X)
|
|
3350
3432
|
string - relevant slots found, in case more than 1 slot found.
|
|
3351
3433
|
"""
|
|
3352
|
-
storage_layouts = [c.
|
|
3353
|
-
c.name == primary_contract and c.
|
|
3434
|
+
storage_layouts = [c.storage_layout for c in sdc.contracts if
|
|
3435
|
+
c.name == primary_contract and c.storage_layout is not None]
|
|
3354
3436
|
if len(storage_layouts) != 1:
|
|
3355
3437
|
build_logger.debug(f"Expected exactly one storage layout matching {primary_contract}, "
|
|
3356
3438
|
f"got {len(storage_layouts)}")
|
|
@@ -3454,6 +3536,42 @@ class CertoraBuildGenerator:
|
|
|
3454
3536
|
|
|
3455
3537
|
return slot_number
|
|
3456
3538
|
|
|
3539
|
+
@staticmethod
|
|
3540
|
+
def get_manual_mutants_file(context: CertoraContext) -> Set[Path]:
|
|
3541
|
+
"""
|
|
3542
|
+
Returns a set of mutant Solidity files based on the manual mutations specified in the context.
|
|
3543
|
+
These files are added to .certora_sources.
|
|
3544
|
+
|
|
3545
|
+
certoraRun generally skips the mutations object therefore no exceptions are raised if mutant files
|
|
3546
|
+
cannot be read due to bad syntax or any other error
|
|
3547
|
+
|
|
3548
|
+
:param context:
|
|
3549
|
+
:return: list of mutants file
|
|
3550
|
+
"""
|
|
3551
|
+
|
|
3552
|
+
def get_sol_files(path: Path) -> Set[Path]:
|
|
3553
|
+
sol_files: Set[Path] = set()
|
|
3554
|
+
|
|
3555
|
+
if path.is_file() and path.suffix == SOL:
|
|
3556
|
+
sol_files.add(path)
|
|
3557
|
+
elif path.is_dir():
|
|
3558
|
+
for file_path in path.rglob(fr'*{SOL}'):
|
|
3559
|
+
sol_files.add(file_path)
|
|
3560
|
+
return sol_files
|
|
3561
|
+
|
|
3562
|
+
result: Set[Path] = set()
|
|
3563
|
+
try:
|
|
3564
|
+
manual_mutations = context.mutations[MANUAL_MUTANTS]
|
|
3565
|
+
for mutation in manual_mutations:
|
|
3566
|
+
try:
|
|
3567
|
+
mutation_path = mutation[MUTANTS_LOCATION]
|
|
3568
|
+
except Exception:
|
|
3569
|
+
continue
|
|
3570
|
+
result |= get_sol_files(Path(mutation_path))
|
|
3571
|
+
except Exception:
|
|
3572
|
+
pass
|
|
3573
|
+
return result
|
|
3574
|
+
|
|
3457
3575
|
# The sources that are collected for the .certora_sources directory are all the files that are provided as input
|
|
3458
3576
|
# (i.e. they are not generated during the certora build process) that are needed for precise rerunning certoraRun.
|
|
3459
3577
|
#
|
|
@@ -3499,6 +3617,7 @@ class CertoraBuildGenerator:
|
|
|
3499
3617
|
if hasattr(context, CONF_FILE_ATTR):
|
|
3500
3618
|
add_to_sources(Path(getattr(context, CONF_FILE_ATTR)))
|
|
3501
3619
|
|
|
3620
|
+
sources |= CertoraBuildGenerator.get_manual_mutants_file(context)
|
|
3502
3621
|
return sources
|
|
3503
3622
|
|
|
3504
3623
|
def __del__(self) -> None:
|
|
@@ -3633,6 +3752,7 @@ def build_from_cache_or_scratch(context: CertoraContext,
|
|
|
3633
3752
|
|
|
3634
3753
|
return cache_hit, True, cached_files
|
|
3635
3754
|
|
|
3755
|
+
|
|
3636
3756
|
def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> None:
|
|
3637
3757
|
"""
|
|
3638
3758
|
This is the main function of certoraBuild
|
|
@@ -38,6 +38,7 @@ def current_conf_to_file(context: CertoraContext) -> Dict[str, Any]:
|
|
|
38
38
|
all_conf_names = Attrs.get_attribute_class().all_conf_names()
|
|
39
39
|
context_to_save = dict(sorted(context_to_save.items(), key=lambda x: all_conf_names.index(x[0])))
|
|
40
40
|
context_to_save.pop('build_dir', None) # build dir should not be saved, each run should define its own build_dir
|
|
41
|
+
context_to_save.pop('mutation_test_id', None) # mutation_test_id should be recreated for every run
|
|
41
42
|
|
|
42
43
|
out_file_path = Util.get_last_conf_file()
|
|
43
44
|
run_logger.debug(f"Saving last configuration file to {out_file_path}")
|
|
@@ -92,39 +92,9 @@ def collect_jar_args(context: CertoraContext) -> List[str]:
|
|
|
92
92
|
for value in prover_args_values:
|
|
93
93
|
return_list.extend(value.split())
|
|
94
94
|
|
|
95
|
-
# CERT-926: Because of the way that the type checker jar and the evm jar command line argument parser
|
|
96
|
-
# is implemented, you cannot have one commandline argument for both jars. As a result we need an argument
|
|
97
|
-
# for the type checker jar and for the evm jar that control whether the CVL type checking code
|
|
98
|
-
# will permit Solidity function calls in CVL quantifier bodies. We prioritize the type checker jar
|
|
99
|
-
# argument "typechecker_args" in the conf files and if it contains the flag "-allowSolidityQuantifierCalls true"
|
|
100
|
-
# we append the prover argument version to the list of prover jar arguments.
|
|
101
|
-
type_checker_values = getattr(context, Attrs.EvmProverAttributes.TYPECHECKER_ARGS.get_conf_key(), None)
|
|
102
|
-
if type_checker_values:
|
|
103
|
-
for value in type_checker_values:
|
|
104
|
-
values = value.split()
|
|
105
|
-
if values[0] == '-allowSolidityQuantifierCalls' and values[1] == 'true':
|
|
106
|
-
return_list.extend(['-allowSolidityCallsInQuantifiers', 'true'])
|
|
107
95
|
return return_list
|
|
108
96
|
|
|
109
97
|
|
|
110
|
-
def get_typechecker_arguments(context: CertoraContext) -> List[str]:
|
|
111
|
-
"""
|
|
112
|
-
Assembles a string of all the command-line options the typechecker cares about
|
|
113
|
-
@param context: The context
|
|
114
|
-
@return: A string with all the options in the format the typechecker understands.
|
|
115
|
-
"""
|
|
116
|
-
args = []
|
|
117
|
-
if context.typechecker_args:
|
|
118
|
-
args += context.typechecker_args
|
|
119
|
-
|
|
120
|
-
relevant_attrs = filter(lambda arg: get_attr_value(context, arg),
|
|
121
|
-
[Attrs.EvmProverAttributes.RULE, Attrs.EvmProverAttributes.EXCLUDE_RULE,
|
|
122
|
-
Attrs.EvmProverAttributes.FOUNDRY_TESTS_MODE])
|
|
123
|
-
args += create_jar_flag_list(context, list(relevant_attrs))
|
|
124
|
-
|
|
125
|
-
return args
|
|
126
|
-
|
|
127
|
-
|
|
128
98
|
def get_local_run_cmd(context: CertoraContext) -> str:
|
|
129
99
|
"""
|
|
130
100
|
Assembles a jar command for local run
|
|
@@ -147,9 +117,6 @@ def get_local_run_cmd(context: CertoraContext) -> str:
|
|
|
147
117
|
certora_root_dir = Util.get_certora_root_directory().as_posix()
|
|
148
118
|
jar_path = f"{certora_root_dir}/{Util.EMV_JAR}"
|
|
149
119
|
|
|
150
|
-
if context.allow_solidity_calls_in_quantifiers:
|
|
151
|
-
run_args.extend(['-allowSolidityCallsInQuantifiers true'])
|
|
152
|
-
|
|
153
120
|
"""
|
|
154
121
|
This flag prevents the focus from being stolen from the terminal when running the java process.
|
|
155
122
|
Stealing the focus makes it seem like the program is not responsive to Ctrl+C.
|
|
@@ -519,7 +486,10 @@ def run_typechecker(typechecker_name: str, with_typechecking: bool, args: List[s
|
|
|
519
486
|
f"{'-typeCheck ' if with_typechecking else ''}" \
|
|
520
487
|
f"{' '.join(args)}"
|
|
521
488
|
|
|
522
|
-
exit_code = Util.run_jar_cmd(typecheck_cmd, False,
|
|
489
|
+
exit_code = Util.run_jar_cmd(typecheck_cmd, False,
|
|
490
|
+
custom_error_message="Failed to run Certora Prover locally. Please check the errors "
|
|
491
|
+
"below for problems in the specifications (.spec files) or the "
|
|
492
|
+
"prover_args defined in the .conf file.",
|
|
523
493
|
logger_topic="type_check")
|
|
524
494
|
if exit_code != 0:
|
|
525
495
|
raise Util.CertoraUserInputError("CVL specification syntax and type check failed")
|
|
@@ -533,9 +503,9 @@ def run_local_spec_check(with_typechecking: bool, context: CertoraContext) -> No
|
|
|
533
503
|
|
|
534
504
|
if context.disable_local_typechecking or Util.is_ci_or_git_action():
|
|
535
505
|
return
|
|
536
|
-
args =
|
|
506
|
+
args = collect_jar_args(context)
|
|
537
507
|
if Util.is_java_installed():
|
|
538
508
|
run_typechecker("Typechecker.jar", with_typechecking, args)
|
|
539
509
|
else:
|
|
540
|
-
raise Util.CertoraUserInputError("Cannot run local checks because of missing a suitable java
|
|
510
|
+
raise Util.CertoraUserInputError("Cannot run local checks because of missing a suitable java installation. "
|
|
541
511
|
"To skip local checks run with the --disable_local_typechecking flag")
|
{certora_cli-7.14.3 → certora_cli-7.17.2}/certora_cli/EVMVerifier/certoraContextAttributes.py
RENAMED
|
@@ -269,6 +269,19 @@ class EvmAttributes(AttrUtil.Attributes):
|
|
|
269
269
|
disables_build_cache=False
|
|
270
270
|
)
|
|
271
271
|
|
|
272
|
+
SOLC_EVM_VERSION_MAP = AttrUtil.AttributeDefinition(
|
|
273
|
+
attr_validation_func=Vf.validate_solc_evm_version_map,
|
|
274
|
+
arg_type=AttrUtil.AttrArgType.MAP,
|
|
275
|
+
help_msg='Map contracts to the appropriate EVM version',
|
|
276
|
+
default_desc="Uses the same Solidity EVM version for all contracts",
|
|
277
|
+
argparse_args={
|
|
278
|
+
'action': AttrUtil.UniqueStore,
|
|
279
|
+
'type': lambda value: Vf.parse_dict('solc_map', value)
|
|
280
|
+
},
|
|
281
|
+
affects_build_cache_key=True,
|
|
282
|
+
disables_build_cache=False
|
|
283
|
+
)
|
|
284
|
+
|
|
272
285
|
SOLC_MAP = AttrUtil.AttributeDefinition(
|
|
273
286
|
attr_validation_func=Vf.validate_solc_map,
|
|
274
287
|
arg_type=AttrUtil.AttrArgType.MAP,
|
|
@@ -496,6 +509,37 @@ class EvmAttributes(AttrUtil.Attributes):
|
|
|
496
509
|
disables_build_cache=False
|
|
497
510
|
)
|
|
498
511
|
|
|
512
|
+
CONTRACT_EXTENSIONS = AttrUtil.AttributeDefinition(
|
|
513
|
+
attr_validation_func=Vf.validate_contract_extension_attr,
|
|
514
|
+
help_msg="Dictionary of extension contracts. Format:\n"
|
|
515
|
+
'{\n'
|
|
516
|
+
' "ExtendedContractA: [\n'
|
|
517
|
+
' {\n'
|
|
518
|
+
' "extension": "ExtenderA",\n'
|
|
519
|
+
' "exclude": [\n'
|
|
520
|
+
' "method1",\n'
|
|
521
|
+
' ...,\n'
|
|
522
|
+
' "methodN"\n'
|
|
523
|
+
' ]\n'
|
|
524
|
+
' },\n'
|
|
525
|
+
' {\n'
|
|
526
|
+
' ...\n'
|
|
527
|
+
' }\n'
|
|
528
|
+
' ],\n'
|
|
529
|
+
' "ExtendedContractB: [\n'
|
|
530
|
+
' ...\n'
|
|
531
|
+
' ],\n'
|
|
532
|
+
' ...\n'
|
|
533
|
+
'}',
|
|
534
|
+
default_desc="",
|
|
535
|
+
affects_build_cache_key=True,
|
|
536
|
+
disables_build_cache=False,
|
|
537
|
+
arg_type=AttrUtil.AttrArgType.MAP,
|
|
538
|
+
argparse_args={
|
|
539
|
+
'action': AttrUtil.UniqueStore
|
|
540
|
+
}
|
|
541
|
+
)
|
|
542
|
+
|
|
499
543
|
PROTOTYPE = AttrUtil.AttributeDefinition(
|
|
500
544
|
attr_validation_func=Vf.validate_prototype_attr,
|
|
501
545
|
arg_type=AttrUtil.AttrArgType.LIST,
|
|
@@ -607,17 +651,6 @@ class EvmAttributes(AttrUtil.Attributes):
|
|
|
607
651
|
disables_build_cache=False
|
|
608
652
|
)
|
|
609
653
|
|
|
610
|
-
TYPECHECKER_ARGS = AttrUtil.AttributeDefinition(
|
|
611
|
-
arg_type=AttrUtil.AttrArgType.LIST,
|
|
612
|
-
help_msg="Send flags directly to the CVL typechecker",
|
|
613
|
-
default_desc="",
|
|
614
|
-
argparse_args={
|
|
615
|
-
'nargs': AttrUtil.ONE_OR_MORE_OCCURRENCES,
|
|
616
|
-
'action': AttrUtil.APPEND
|
|
617
|
-
},
|
|
618
|
-
affects_build_cache_key=False,
|
|
619
|
-
disables_build_cache=False
|
|
620
|
-
)
|
|
621
654
|
INTERNAL_FUNCS = AttrUtil.AttributeDefinition(
|
|
622
655
|
attr_validation_func=Vf.validate_json_file,
|
|
623
656
|
argparse_args={
|
|
@@ -767,8 +800,6 @@ class InternalUseAttributes(AttrUtil.Attributes):
|
|
|
767
800
|
)
|
|
768
801
|
|
|
769
802
|
|
|
770
|
-
|
|
771
|
-
|
|
772
803
|
class BackendAttributes(AttrUtil.Attributes):
|
|
773
804
|
|
|
774
805
|
UNUSED_SUMMARY_HARD_FAIL = AttrUtil.AttributeDefinition(
|
|
@@ -1334,6 +1365,7 @@ class BackendAttributes(AttrUtil.Attributes):
|
|
|
1334
1365
|
|
|
1335
1366
|
ALLOW_SOLIDITY_CALLS_IN_QUANTIFIERS = AttrUtil.AttributeDefinition(
|
|
1336
1367
|
arg_type=AttrUtil.AttrArgType.BOOLEAN,
|
|
1368
|
+
jar_flag='-allowSolidityQuantifierCalls',
|
|
1337
1369
|
argparse_args={
|
|
1338
1370
|
'action': AttrUtil.STORE_TRUE
|
|
1339
1371
|
},
|
|
@@ -1403,7 +1435,7 @@ def set_attribute_class(cls: Type[AttrUtil.Attributes]) -> None:
|
|
|
1403
1435
|
|
|
1404
1436
|
def detect_application_class(args: List[str]) -> Type[AttrUtil.Attributes]:
|
|
1405
1437
|
evm_suffixes = ('.sol', '.vy', '.yul', '.tac', '.json')
|
|
1406
|
-
wasm_suffixes = '.wat'
|
|
1438
|
+
wasm_suffixes = ('.wat', '.wasm')
|
|
1407
1439
|
solana_suffixes = ('.so', '.o')
|
|
1408
1440
|
|
|
1409
1441
|
attributes_logger.debug("calling detect_application_class")
|