certora-cli 8.19.2__tar.gz → 8.20.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.
Files changed (95) hide show
  1. {certora_cli-8.19.2/certora_cli.egg-info → certora_cli-8.20.2}/PKG-INFO +2 -2
  2. certora_cli-8.20.2/README.md +1 -0
  3. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollector.py +14 -0
  4. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollectorFactory.py +39 -19
  5. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraBuild.py +91 -39
  6. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraBuildDataClasses.py +4 -0
  7. certora_cli-8.20.2/certora_cli/CertoraProver/certoraBuildRust.py +351 -0
  8. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraCloudIO.py +119 -55
  9. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraContextValidator.py +22 -7
  10. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraJobList.py +10 -5
  11. certora_cli-8.20.2/certora_cli/CertoraProver/test_certoraCloudIO.py +157 -0
  12. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/mutateApp.py +85 -92
  13. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/mutateConstants.py +3 -11
  14. certora_cli-8.20.2/certora_cli/Mutate/test_mutateApp.py +60 -0
  15. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/certoraUtils.py +44 -1
  16. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/proverCommon.py +7 -4
  17. certora_cli-8.20.2/certora_cli/Shared/test_proverCommon.py +76 -0
  18. {certora_cli-8.19.2 → certora_cli-8.20.2/certora_cli.egg-info}/PKG-INFO +2 -2
  19. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli.egg-info/SOURCES.txt +3 -0
  20. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_jars/ASTExtraction.jar +0 -0
  21. certora_cli-8.20.2/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
  22. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_jars/Typechecker.jar +0 -0
  23. {certora_cli-8.19.2 → certora_cli-8.20.2}/setup.py +2 -2
  24. certora_cli-8.19.2/README.md +0 -1
  25. certora_cli-8.19.2/certora_cli/CertoraProver/certoraBuildRust.py +0 -154
  26. certora_cli-8.19.2/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
  27. {certora_cli-8.19.2 → certora_cli-8.20.2}/LICENSE +0 -0
  28. {certora_cli-8.19.2 → certora_cli-8.20.2}/MANIFEST.in +0 -0
  29. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_bins/__init__.py +0 -0
  30. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollectorSol.py +0 -0
  31. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollectorSolBased.py +0 -0
  32. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollectorVy.py +0 -0
  33. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/CompilerCollectorYul.py +0 -0
  34. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/Compiler/__init__.py +0 -0
  35. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/__init__.py +0 -0
  36. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/castingInstrumenter.py +0 -0
  37. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraApp.py +0 -0
  38. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraBuildCacheManager.py +0 -0
  39. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraBuildSui.py +0 -0
  40. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraCollectConfigurationLayout.py +0 -0
  41. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraCollectRunMetadata.py +0 -0
  42. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraCompilerParameters.py +0 -0
  43. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraConfigIO.py +0 -0
  44. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraContext.py +0 -0
  45. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraContextAttributes.py +0 -0
  46. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraContextClass.py +0 -0
  47. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraContractFuncs.py +0 -0
  48. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraExtensionInfo.py +0 -0
  49. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraMiniSpecParser.py +0 -0
  50. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraNodeFilters.py +0 -0
  51. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraOffsetConverter.py +0 -0
  52. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraParseBuildScript.py +0 -0
  53. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraProjectScanner.py +0 -0
  54. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraSourceFinders.py +0 -0
  55. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraType.py +0 -0
  56. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/certoraVerifyGenerator.py +0 -0
  57. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/erc7201.py +0 -0
  58. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/splitRules.py +0 -0
  59. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/storageExtension.py +0 -0
  60. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/CertoraProver/uncheckedOverflowInstrumenter.py +0 -0
  61. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
  62. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
  63. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
  64. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
  65. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
  66. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/__init__.py +0 -0
  67. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
  68. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
  69. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/__init__.py +0 -0
  70. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/mutateAttributes.py +0 -0
  71. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/mutateUtil.py +0 -0
  72. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Mutate/mutateValidate.py +0 -0
  73. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/ExpectedComparator.py +0 -0
  74. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/__init__.py +0 -0
  75. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/certoraAttrUtil.py +0 -0
  76. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/certoraLogging.py +0 -0
  77. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/Shared/certoraValidateFuncs.py +0 -0
  78. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/__init__.py +0 -0
  79. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraCVLFormatter.py +0 -0
  80. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraConcord.py +0 -0
  81. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraEVMProver.py +0 -0
  82. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraEqCheck.py +0 -0
  83. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraMutate.py +0 -0
  84. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraRanger.py +0 -0
  85. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraRun.py +0 -0
  86. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraSolanaProver.py +0 -0
  87. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraSorobanProver.py +0 -0
  88. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/certoraSuiProver.py +0 -0
  89. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli/rustMutator.py +0 -0
  90. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli.egg-info/dependency_links.txt +0 -0
  91. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli.egg-info/entry_points.txt +0 -0
  92. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli.egg-info/requires.txt +0 -0
  93. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_cli.egg-info/top_level.txt +0 -0
  94. {certora_cli-8.19.2 → certora_cli-8.20.2}/certora_jars/__init__.py +0 -0
  95. {certora_cli-8.19.2 → certora_cli-8.20.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: certora-cli
3
- Version: 8.19.2
3
+ Version: 8.20.2
4
4
  Summary: Runner for the Certora Prover
5
5
  Home-page: https://pypi.org/project/certora-cli
6
6
  Author: Certora
@@ -38,4 +38,4 @@ Dynamic: requires-dist
38
38
  Dynamic: requires-python
39
39
  Dynamic: summary
40
40
 
41
- Commit 63fdea8. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
41
+ Commit f5f7778. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -0,0 +1 @@
1
+ Commit f5f7778. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -190,6 +190,20 @@ class CompilerCollector(ABC):
190
190
  def compiler_version(self) -> CompilerVersion:
191
191
  pass
192
192
 
193
+ # Full version identifier from the compiler's `--version` output
194
+ # (e.g. solc '0.8.34+commit.80d5c536.Darwin.appleclang'), recording the exact
195
+ # compiler build. None when it could not be extracted. Set by the factory after
196
+ # construction so subclass constructors need not change.
197
+ _compiler_version_full: Optional[str] = None
198
+
199
+ @property
200
+ def compiler_version_full(self) -> Optional[str]:
201
+ return self._compiler_version_full
202
+
203
+ @compiler_version_full.setter
204
+ def compiler_version_full(self, value: Optional[str]) -> None:
205
+ self._compiler_version_full = value
206
+
193
207
  def normalize_file_compiler_path_name(self, file_abs_path: str) -> str:
194
208
  """
195
209
  Normalizes the absolute path name [file_abs_path] of a file, given to the compiler.
@@ -18,7 +18,7 @@ import os
18
18
  from Shared import certoraUtils as Util
19
19
  from pathlib import Path
20
20
  from functools import lru_cache
21
- from typing import Set, Callable
21
+ from typing import Set, Callable, Tuple, Optional
22
22
  import re
23
23
  import logging
24
24
  from CertoraProver.Compiler.CompilerCollector import CompilerLang, CompilerCollector
@@ -94,44 +94,48 @@ class CompilerCollectorFactory:
94
94
  @param path: path of the file to create [CompilerCollector] for
95
95
  """
96
96
  if str(path).endswith(".vy"):
97
- version = self.__get_vyper_version(path)
98
- return CompilerCollectorVy(version)
97
+ version, full_version = self.__get_vyper_version(path)
98
+ collector: CompilerCollector = CompilerCollectorVy(version)
99
99
  elif str(path).endswith(".sol"):
100
- version = self.__get_solc_version(path)
101
-
102
- return CompilerCollectorSol(version, CompilerLangSol(), not self.context.no_memory_safe_autofinders)
100
+ version, full_version = self.__get_solc_version(path)
101
+ collector = CompilerCollectorSol(version, CompilerLangSol(), not self.context.no_memory_safe_autofinders)
103
102
  elif str(path).endswith(".yul"):
104
- version = self.__get_solc_version(path)
105
- return CompilerCollectorYul(version, CompilerLangYul())
103
+ version, full_version = self.__get_solc_version(path)
104
+ collector = CompilerCollectorYul(version, CompilerLangYul())
106
105
  else:
107
106
  raise RuntimeError(f'expected {path} to represent a Solidity, Yul, or Vyper file')
108
107
 
109
- def __get_vyper_version(self, contract_file_path: Path) -> Util.CompilerVersion:
108
+ collector.compiler_version_full = full_version
109
+ return collector
110
+
111
+ def __get_vyper_version(self, contract_file_path: Path) -> Tuple[Util.CompilerVersion, Optional[str]]:
110
112
  """
111
113
  @param contract_file_path: the contract that we are working on
112
- @return: the running Vyper version
114
+ @return: the running Vyper version (triplet, full identifier)
113
115
  """
114
116
  vyper_exec_to_run = get_relevant_compiler(contract_file_path, self.context)
115
- version = self.__get_compiler_exe_version(vyper_exec_to_run, self.__version_string_handler_vyper)
116
- return version
117
+ return self.__get_compiler_exe_version(vyper_exec_to_run, self.__version_string_handler_vyper)
117
118
 
118
- def __get_solc_version(self, contract_file_path: Path) -> Util.CompilerVersion:
119
+ def __get_solc_version(self, contract_file_path: Path) -> Tuple[Util.CompilerVersion, Optional[str]]:
119
120
  """
120
121
  @param contract_file_path: the contract that we are working on
121
- @return: the running solc version
122
+ @return: the running solc version (triplet, full identifier)
122
123
  """
123
124
  compiler_logger.debug(f"visiting contract file {contract_file_path}")
124
125
  solc_path = get_relevant_compiler(contract_file_path, self.context)
125
- version = self.__get_compiler_exe_version(solc_path, self.__version_string_handler_solc)
126
- return version
126
+ return self.__get_compiler_exe_version(solc_path, self.__version_string_handler_solc)
127
127
 
128
128
  @lru_cache(maxsize=32)
129
129
  def __get_compiler_exe_version(self, compiler_name: str,
130
130
  version_string_handler:
131
- Callable[[str], Util.CompilerVersion]) -> Util.CompilerVersion:
131
+ Callable[[str], Util.CompilerVersion]) -> Tuple[Util.CompilerVersion, Optional[str]]:
132
132
  """
133
133
  @param compiler_name: name of the solc we want to run on this contract
134
- @return: the running compiler version
134
+ @return: a tuple of (the running compiler version triplet, the full version
135
+ identifier string from `--version` such as
136
+ '0.8.34+commit.80d5c536.Darwin.appleclang', or None if it could not
137
+ be extracted). The triplet is used for behavioural checks; the full
138
+ identifier records the exact compiler build for reproducibility.
135
139
  """
136
140
  out_name = f"version_check_{Path(compiler_name).name}"
137
141
  stdout_path = get_certora_config_dir() / f'{out_name}.stdout'
@@ -146,7 +150,23 @@ class CompilerCollectorFactory:
146
150
 
147
151
  with stdout_path.open() as r:
148
152
  version_string = r.read(-1)
149
- return version_string_handler(version_string)
153
+ return version_string_handler(version_string), self.__extract_full_version(version_string)
154
+
155
+ @staticmethod
156
+ def __extract_full_version(version_string: str) -> Optional[str]:
157
+ """
158
+ Extracts the full version identifier from a compiler's `--version` output.
159
+ solc prints a `Version: <id>` line (e.g. 'Version: 0.8.34+commit.80d5c536.Darwin.appleclang');
160
+ vyper prints the bare identifier. Returns the identifier token, or None if not found.
161
+ """
162
+ version_matches = re.findall(r'^Version:\s*(\S+)', version_string, re.MULTILINE)
163
+ if version_matches:
164
+ return version_matches[0]
165
+ for line in version_string.splitlines():
166
+ line = line.strip()
167
+ if line:
168
+ return line
169
+ return None
150
170
 
151
171
  @staticmethod
152
172
  def __version_string_handler_vyper(version_string: str) -> Util.CompilerVersion:
@@ -468,6 +468,25 @@ def convert_pathname_to_posix(json_dict: Dict[str, Any], entry: str, compiler_co
468
468
  json_dict[entry] = json_dict_posix_paths
469
469
 
470
470
 
471
+ def relative_import_path(importer_dir: Path, target: str) -> str:
472
+ """
473
+ The path under which a Solidity file in [importer_dir] imports [target].
474
+ solc resolves an import starting with `./` or `../` against the importing file's directory.
475
+ """
476
+ rel = Util.as_posix(os.path.relpath(Util.abs_posix_path(target), Util.abs_posix_path(importer_dir)))
477
+ return rel if rel.startswith("../") else f"./{rel}"
478
+
479
+
480
+ def harness_import_path(importer_dir: Path, target: str) -> str:
481
+ """
482
+ The path under which a harness in [importer_dir] imports [target], a solc source unit name from the main build.
483
+ A name that does not start with `./` or `../` is imported as is, so solc gives the file the same name as in the
484
+ main build and loads it once even if the harness also reaches it through other imports. A name that does would be
485
+ resolved against the harness's directory, so it is rewritten relative to it.
486
+ """
487
+ return relative_import_path(importer_dir, target) if target.startswith(("./", "../")) else target
488
+
489
+
471
490
  class CertoraBuildGenerator:
472
491
  # 12,14,04,06,00,04,10 is 0xce4604a aka certora.
473
492
  CONSTRUCTOR_STRING = "constructor"
@@ -1438,6 +1457,19 @@ class CertoraBuildGenerator:
1438
1457
  if match:
1439
1458
  settings_dict["evmVersion"] = match
1440
1459
 
1460
+ @staticmethod
1461
+ def _solc_takes_inliner_detail(compiler_version: Tuple[int, int, int]) -> bool:
1462
+ """Whether this compiler accepts `settings.optimizer.details.inliner`.
1463
+
1464
+ solc learned the key in 0.8.5; older compilers reject the whole standard-json input with
1465
+ `Unknown key "inliner"`, so the file fails to compile rather than compiling un-inlined.
1466
+ See https://github.com/ethereum/solidity/blob/v0.8.4/libsolidity/interface/StandardCompiler.cpp
1467
+ """
1468
+ major, minor, patch = compiler_version
1469
+ if major != 0:
1470
+ raise Util.CertoraUserInputError(f"Unrecognized version {major}.{minor}.{patch}")
1471
+ return (minor == 8 and patch >= 5) or (minor > 8)
1472
+
1441
1473
  def _handle_optimize(self, contract_file_path: Path, settings_dict: Dict[str, Any],
1442
1474
  compiler_collector: CompilerCollector) -> None:
1443
1475
  """
@@ -1456,29 +1488,47 @@ class CertoraBuildGenerator:
1456
1488
  if optimizer and isinstance(optimizer, dict) and optimizer.get('enabled'):
1457
1489
  # if we are not disabling finder friendly optimizer specifically, enable it whenever viaIR is also enabled
1458
1490
  if not self.context.strict_solc_optimizer and self.get_solc_via_ir_value(contract_file_path):
1459
- # The default optimizer steps (taken from libsolidity/interface/OptimiserSettings.h) but with the
1460
- # full inliner step removed
1461
- solc0_8_34_to_0_8_36 = ("dfDvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLvifMCTUca[r]LSsTFOtfDnca[r]"
1462
- "IulcscCTUtvifMx[scCTUt]TOntnfDIulvifMjmul[jul]VcTOculjmul")
1463
- solc0_8_26_to_0_8_33 = ("dhfoDgvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLCTUca[r]LSsTFOtfDnca[r]" +
1464
- "IulcscCTUtx[scCTUt]TOntnfDIuljmul[jul]VcTOculjmul")
1465
- solc0_8_13_to_0_8_25 = "dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]T" + \
1466
- "peulxa[rul]xa[r]cLgvifCTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
1467
- solc0_8_12 = "dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]T" + \
1468
- "peulxa[rul]xa[r]cLgvifCTUca[r]LsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
1469
- solc0_8_10_to_0_8_11 = "dhfoDgvulfnTUtnIf[xa[r]scLMcCTUtTOntnfDIulLculVcul[j]T" + \
1470
- "peulxa[rul]xa[r]cLgvifCTUca[r]LsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
1471
- solc0_8_1_to_0_8_9 = "dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjT" + \
1472
- "peulxarulrulxarrcLgvifCTUcarrLsTFOtfDncarrIulc]jmuljuljulVcTOculjmul"
1473
- solc0_7_6_to_0_8_0 = "dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjT" + \
1474
- "peulxarulrulxarrcLgvifCTUcarrLsTFOtfDncarrIulc]jmuljuljulVcTOculjmul"
1475
- solc0_7_2_to_0_7_5 = "NdhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjT" + \
1476
- "peulxarulrulxarrcLgvifCTUcarrLsTFOtfDncarrIulc]jmuljuljulVcTOculjmulN"
1477
- solc0_6_7_to_0_7_1 = "dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjj" + \
1478
- "eulxarulrulxarrcLgvifCTUcarrLsTFOtfDncarrIulc]jmuljuljulVcTOculjmul"
1479
-
1480
- def standard_replacement(optimizer_steps: str) -> str:
1481
- return optimizer_steps.replace("gvif", "gvf") # replace gvif with gvf
1491
+ # The default Yul optimizer steps, copied verbatim from
1492
+ # libsolidity/interface/OptimiserSettings.h at each release that changed them. Keeping them
1493
+ # verbatim is what makes the full inliner the only difference between what we send and what
1494
+ # solc would have run by itself.
1495
+ solc0_8_34_to_0_8_36 = ("dfDvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLvifMCTUca[r]LSsTFOtfDnca[r]Iulcsc"
1496
+ "CTUtvifMx[scCTUt]TOntnfDIulvifMjmul[jul]VcTOculjmul")
1497
+ solc0_8_26_to_0_8_33 = ("dhfoDgvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLgvifMCTUca[r]LSsTFOtfDnca[r]Iu"
1498
+ "lcscCTUtgvifMx[scCTUt]TOntnfDIulgvifMjmul[jul]VcTOculjmul")
1499
+ solc0_8_13_to_0_8_25 = ("dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]Tpeulxa[rul]xa[r]cLgvif"
1500
+ "CTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul")
1501
+ solc0_8_12 = ("dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]Tpeulxa[rul]xa[r]cLgvifCTUca[r]Ls"
1502
+ "TFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul")
1503
+ solc0_8_10_to_0_8_11 = ("dhfoDgvulfnTUtnIf[xa[r]scLMcCTUtTOntnfDIulLculVcul[j]Tpeulxa[rul]xa[r]cLgvifC"
1504
+ "TUca[r]LsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul")
1505
+ solc0_8_4_to_0_8_9 = ("dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvifCTUca"
1506
+ "rrLsTFOtfDncarrIulc]jmuljuljulVcTOculjmul")
1507
+ solc0_7_6_to_0_8_3 = ("dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvifCTUca"
1508
+ "rrLsTOtfDncarrIulc]jmuljuljulVcTOculjmul")
1509
+ solc0_7_2_to_0_7_5 = ("NdhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjTpeulxarulrulxarrcLgvifCTUc"
1510
+ "arrLsTOtfDncarrIulc]jmuljuljulVcTOculjmulN")
1511
+ solc0_6_7_to_0_7_1 = ("dhfoDgvulfnTUtnIf[xarrscLMcCTUtTOntnfDIulLculVculjjeulxarulrulxarrcLgvifCTUcarr"
1512
+ "LsTOtfDncarrIulc]jmuljuljulVcTOculjmul")
1513
+
1514
+ def without_full_inliner(optimizer_steps: str) -> str:
1515
+ """Take the full inliner out of a Yul optimizer step sequence.
1516
+
1517
+ The full inliner pulls internal functions into their callers, which erases the autofinders
1518
+ that internal-function summaries are matched against. It is the letter `i`, and in every
1519
+ sequence solc ships it appears only inside the trigram `vif`: EquivalentFunctionCombiner,
1520
+ FullInliner, BlockFlattener, the flattener being there to tidy up after the inliner. Dropping
1521
+ the middle letter of that trigram removes the inliner and leaves every other pass in place
1522
+ and in order.
1523
+
1524
+ Upstream writes the trigram plus its surrounding steps as one line in
1525
+ OptimiserSettings.h and comments the whole line "Run full inliner", so it is tempting to
1526
+ drop all of it. On every rung here, taking out `i` alone keeps just as many internal
1527
+ functions as taking out the whole group, so this is the smaller deviation from what solc
1528
+ would have run for the same result. Public/CITests/testYulOptimizerStepsInlining.py is
1529
+ what checks the rewrite still does its job on each compiler.
1530
+ """
1531
+ return optimizer_steps.replace("vif", "vf")
1482
1532
 
1483
1533
  compiler_version = compiler_collector.compiler_version
1484
1534
  major, minor, patch = compiler_version
@@ -1499,10 +1549,10 @@ class CertoraBuildGenerator:
1499
1549
  yul_optimizer_steps = solc0_6_7_to_0_7_1
1500
1550
  elif minor == 7 and 2 <= patch <= 5:
1501
1551
  yul_optimizer_steps = solc0_7_2_to_0_7_5
1502
- elif (minor == 7 and 6 <= patch) or (minor == 8 and patch == 0):
1503
- yul_optimizer_steps = solc0_7_6_to_0_8_0
1504
- elif minor == 8 and 1 <= patch <= 9:
1505
- yul_optimizer_steps = solc0_8_1_to_0_8_9
1552
+ elif (minor == 7 and 6 <= patch) or (minor == 8 and patch <= 3):
1553
+ yul_optimizer_steps = solc0_7_6_to_0_8_3
1554
+ elif minor == 8 and 4 <= patch <= 9:
1555
+ yul_optimizer_steps = solc0_8_4_to_0_8_9
1506
1556
  elif minor == 8 and 10 <= patch <= 11:
1507
1557
  yul_optimizer_steps = solc0_8_10_to_0_8_11
1508
1558
  elif minor == 8 and patch == 12:
@@ -1516,17 +1566,19 @@ class CertoraBuildGenerator:
1516
1566
  assert yul_optimizer_steps is not None, \
1517
1567
  'Yul Optimizer steps missing for requested Solidity version. Please contact Certora team.'
1518
1568
 
1519
- yul_optimizer_steps = standard_replacement(yul_optimizer_steps)
1520
-
1521
- settings_dict["optimizer"]["details"] = {"inliner": False, "yulDetails": {
1522
- "optimizerSteps": yul_optimizer_steps
1523
- }}
1569
+ yul_optimizer_steps = without_full_inliner(yul_optimizer_steps)
1570
+ assert self.context.yul_optimizer_steps or "i" not in yul_optimizer_steps, \
1571
+ 'Full inliner still present in the Yul optimizer steps. Please contact Certora team.'
1572
+
1573
+ # The Yul steps carry the inlining decision for the via-IR pipeline on every
1574
+ # supported version; `inliner` speaks to the legacy-codegen inliner and exists only
1575
+ # from 0.8.5, so it is added where it is understood and left out where it is not.
1576
+ details: Dict[str, Any] = {"yulDetails": {"optimizerSteps": yul_optimizer_steps}}
1577
+ if self._solc_takes_inliner_detail(compiler_version):
1578
+ details["inliner"] = False
1579
+ settings_dict["optimizer"]["details"] = details
1524
1580
  elif not self.context.strict_solc_optimizer:
1525
- compiler_version = compiler_collector.compiler_version
1526
- major, minor, patch = compiler_version
1527
- if major != 0:
1528
- raise Util.CertoraUserInputError(f"Unrecognized version {major}.{minor}.{patch}")
1529
- if (minor == 8 and patch >= 5) or (minor > 8):
1581
+ if self._solc_takes_inliner_detail(compiler_collector.compiler_version):
1530
1582
  settings_dict["optimizer"]["details"] = {"inliner": False}
1531
1583
  if self.context.disable_solc_optimizers is not None:
1532
1584
  if "details" not in settings_dict["optimizer"]:
@@ -3082,7 +3134,7 @@ class CertoraBuildGenerator:
3082
3134
  # Note we import and don't inline the file's contents since that's how the
3083
3135
  # original file is accessed also in the actual code, and compiling it
3084
3136
  # directly can cause issues.
3085
- tmp_file.write(f"import \"{original_file}\";\n\n")
3137
+ tmp_file.write(f"import \"{harness_import_path(file_dir, original_file)}\";\n\n")
3086
3138
  rel_path = os.path.relpath(tmp_file.name, Path.cwd())
3087
3139
  tmp_abs_path = Util.abs_posix_path(tmp_file.name)
3088
3140
  # Add the temp file to all map attributes so that map lookups
@@ -3146,7 +3198,7 @@ class CertoraBuildGenerator:
3146
3198
  current_content = tmp_file.read()
3147
3199
 
3148
3200
  # Prepare modified content with target import at the beginning
3149
- rel_target_path = os.path.relpath(target_file, Path.cwd())
3201
+ rel_target_path = harness_import_path(file_dir, target_file)
3150
3202
  modified_content = f'import "{rel_target_path}";\n{current_content}'
3151
3203
 
3152
3204
  # Write modified content
@@ -194,6 +194,10 @@ class ContractInSDC:
194
194
  "solidityTypes": [x.as_dict() for x in self.types],
195
195
  "compilerName": "" if not self.compiler_collector else self.compiler_collector.compiler_name,
196
196
  "compilerVersion": self.compiler_version,
197
+ # Full compiler build identifier from `--version` (e.g.
198
+ # '0.8.34+commit.80d5c536.Darwin.appleclang'); additive alongside the
199
+ # triplet-only compilerVersion above. None if unavailable.
200
+ "compilerVersionFull": None if not self.compiler_collector else self.compiler_collector.compiler_version_full,
197
201
  "compilerParameters": None if not self.compiler_parameters else self.compiler_parameters.as_dict(),
198
202
  "sourceBytes": None if self.source_bytes is None else self.source_bytes.as_dict(),
199
203
  "extensionContracts": [e.as_dict() for e in self.extension_contracts],