certora-cli-beta-mirror 8.3.1__py3-none-macosx_10_9_universal2.whl → 8.4.1__py3-none-macosx_10_9_universal2.whl

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.
@@ -1543,7 +1543,8 @@ class CertoraBuildGenerator:
1543
1543
  contract_file_posix_abs: Path,
1544
1544
  contract_file_as_provided: str,
1545
1545
  remappings: List[str],
1546
- compiler_collector: CompilerCollector) -> Dict[str, Any]:
1546
+ compiler_collector: CompilerCollector,
1547
+ compile_wd: Path) -> Dict[str, Any]:
1547
1548
  """
1548
1549
  when calling solc with the standard_json api, instead of passing it flags, we pass it json to request what we
1549
1550
  want -- currently we only use this to retrieve storage layout as this is the only way to do that,
@@ -1554,9 +1555,10 @@ class CertoraBuildGenerator:
1554
1555
  @param compiler_collector: Solidity or Vyper compiler collector
1555
1556
  @return:
1556
1557
  """
1558
+ solc_json_contract_key = os.path.relpath(contract_file_as_provided, compile_wd) if self.context.use_relpaths_for_solc_json else contract_file_posix_abs
1557
1559
  compiler_collector_lang = compiler_collector.smart_contract_lang
1558
1560
  if compiler_collector_lang == CompilerLangSol() or compiler_collector_lang == CompilerLangYul():
1559
- sources_dict = {str(contract_file_posix_abs): {
1561
+ sources_dict = {str(solc_json_contract_key): {
1560
1562
  "urls": [str(contract_file_posix_abs)]}} # type: Dict[str, Dict[str, Any]]
1561
1563
  output_selection = ["transientStorageLayout", "storageLayout", "abi", "evm.bytecode",
1562
1564
  "evm.deployedBytecode", "evm.methodIdentifiers", "evm.assembly",
@@ -1853,7 +1855,7 @@ class CertoraBuildGenerator:
1853
1855
  # Standard JSON
1854
1856
  remappings = [] if isinstance(compiler_collector, CompilerCollectorYul) else self.context.remappings
1855
1857
  input_for_solc = self.standard_json(Path(file_abs_path), build_arg_contract_file, remappings,
1856
- compiler_collector)
1858
+ compiler_collector, compile_wd)
1857
1859
  standard_json_input = json.dumps(input_for_solc).encode("utf-8")
1858
1860
  compiler_logger.debug(f"about to run in {compile_wd} the command: {collect_cmd}")
1859
1861
  compiler_logger.debug(f"solc input = {json.dumps(input_for_solc, indent=4)}")
@@ -1909,7 +1911,7 @@ class CertoraBuildGenerator:
1909
1911
  contract_file_abs = str(Util.abs_norm_path(contract_file))
1910
1912
 
1911
1913
  # using os.path.relpath because Path.relative_to cannot go up the directory tree (no ..)
1912
- contract_file_rel = os.path.relpath(Path(contract_file_abs), Path.cwd())
1914
+ contract_file_rel = os.path.relpath(Path(contract_file_abs), compile_wd)
1913
1915
 
1914
1916
  build_logger.debug(f"available keys: {data['contracts'].keys()}")
1915
1917
  if contract_file_rel in data[CONTRACTS]:
@@ -2008,7 +2010,15 @@ class CertoraBuildGenerator:
2008
2010
  srclist = {"0": file_abs_path}
2009
2011
  report_srclist = {"0": file_abs_path}
2010
2012
 
2011
- report_source_file = report_srclist[[idx for idx in srclist if srclist[idx] == file_abs_path][0]]
2013
+ # Annoyingly, this is currently used just for... presentation?!
2014
+ # We should clean up report_source_file from all places...
2015
+
2016
+ build_logger.debug(f"Finding report source file, abs path {file_abs_path} relative to {compile_wd}")
2017
+ if self.context.use_relpaths_for_solc_json:
2018
+ orig_report_source_file = Util.abs_posix_path(os.path.relpath(file_abs_path, compile_wd))
2019
+ else:
2020
+ orig_report_source_file = file_abs_path
2021
+ report_source_file = report_srclist[[idx for idx in srclist if Util.abs_posix_path(srclist[idx]) == orig_report_source_file][0]]
2012
2022
 
2013
2023
  # all "contracts in SDC" are the same for every primary contract of the compiled file.
2014
2024
  # we can therefore compute those just once...
@@ -2039,8 +2049,9 @@ class CertoraBuildGenerator:
2039
2049
 
2040
2050
  build_logger.debug(f"finding primary contract address of {file_compiler_path}:{primary_contract} in "
2041
2051
  f"{contracts_with_chosen_addresses}")
2052
+ path_to_find = os.path.relpath(file_compiler_path, compile_wd) if self.context.use_relpaths_for_solc_json else file_compiler_path
2042
2053
  primary_contract_address = \
2043
- self.find_contract_address_str(file_compiler_path,
2054
+ self.find_contract_address_str(path_to_find,
2044
2055
  primary_contract,
2045
2056
  contracts_with_chosen_addresses)
2046
2057
  build_logger.debug(f"Contracts in SDC {sdc_name}: {[contract.name for contract in contracts_in_sdc]}")
@@ -2086,7 +2097,7 @@ class CertoraBuildGenerator:
2086
2097
  if new_path is None:
2087
2098
  file_abs_path = Util.abs_posix_path(build_arg_contract_file)
2088
2099
  # for vyper, because there are no autofinders, at least find the main file
2089
- if (orig_file == file_abs_path and
2100
+ if (Util.abs_posix_path(orig_file) == file_abs_path and
2090
2101
  ((Util.get_certora_sources_dir() / build_arg_contract_file).exists() or
2091
2102
  Path(build_arg_contract_file).exists())):
2092
2103
  new_srclist_map[idx] = build_arg_contract_file
@@ -2101,6 +2112,7 @@ class CertoraBuildGenerator:
2101
2112
  report_srclist = srclist
2102
2113
  else:
2103
2114
  report_srclist = srclist
2115
+ build_logger.debug(f"Report source list={report_srclist}")
2104
2116
  return report_srclist
2105
2117
 
2106
2118
  def get_bytecode(self,
@@ -2108,7 +2120,7 @@ class CertoraBuildGenerator:
2108
2120
  contract_name: str,
2109
2121
  primary_contracts: List[str],
2110
2122
  contracts_with_chosen_addresses: List[Tuple[int, Any]],
2111
- fail_if_no_bytecode: bool
2123
+ is_deployed_bytecode: bool
2112
2124
  ) -> str:
2113
2125
  """
2114
2126
  Computes the linked bytecode object from the Solidity compiler output.
@@ -2119,20 +2131,31 @@ class CertoraBuildGenerator:
2119
2131
  @param primary_contracts - the names of the primary contracts we check to have a bytecode
2120
2132
  @param contracts_with_chosen_addresses - a list of tuples of addresses and the
2121
2133
  associated contract identifier
2122
- @param fail_if_no_bytecode - true if the function should fail if bytecode object is missing,
2134
+ @param is_deployed_bytecode - true if we deal with deployed (runtime) bytecode,
2135
+ thus the function should fail if bytecode object is missing,
2123
2136
  false otherwise
2124
2137
  @returns linked bytecode object
2125
2138
  """
2126
2139
  # TODO: Only contract_name should be necessary. This requires a lot more test cases to make sure we're not
2127
2140
  # missing any weird solidity outputs.
2128
2141
  bytecode_ = bytecode_object["object"]
2129
- bytecode = self.collect_and_link_bytecode(contract_name, contracts_with_chosen_addresses,
2130
- bytecode_, bytecode_object.get("linkReferences", {}))
2142
+ try:
2143
+ bytecode = self.collect_and_link_bytecode(contract_name, contracts_with_chosen_addresses,
2144
+ bytecode_, bytecode_object.get("linkReferences", {}))
2145
+ except Util.CertoraUserInputError as e:
2146
+ if is_deployed_bytecode:
2147
+ raise e
2148
+ else:
2149
+ prefix_msg = f"Failed to find a dependency library while building the "\
2150
+ f"constructor bytecode of {contract_name}. "\
2151
+ f"If you need the contract, import the missing library directly and add a dummy usage:\n"
2152
+ orig_msg = str(e)
2153
+ raise Util.CertoraUserInputError(prefix_msg + orig_msg)
2131
2154
  if contract_name in primary_contracts and len(bytecode) == 0:
2132
2155
  msg = f"Contract {contract_name} has no bytecode. " \
2133
2156
  f"It may be caused because the contract is abstract, " \
2134
2157
  f"or is missing constructor code. Please check the output of the Solidity compiler."
2135
- if fail_if_no_bytecode:
2158
+ if is_deployed_bytecode:
2136
2159
  raise Util.CertoraUserInputError(msg)
2137
2160
  else:
2138
2161
  build_logger.warning(msg)
@@ -3002,7 +3025,7 @@ class CertoraBuildGenerator:
3002
3025
  target_file = self.context.contract_to_file[target.name]
3003
3026
  base_contracts = self.retrieve_base_contracts_list(
3004
3027
  target_file,
3005
- Util.abs_posix_path(target_file),
3028
+ target_file if self.context.use_relpaths_for_solc_json else Util.abs_posix_path(target_file),
3006
3029
  target.name
3007
3030
  )
3008
3031
  extensions: Set[str] = set()
@@ -3078,8 +3101,9 @@ class CertoraBuildGenerator:
3078
3101
 
3079
3102
  # let's try to find the AST now
3080
3103
  build_file_ast = None
3104
+ orig_path = os.path.relpath(ext_instance.original_file, Path.cwd()) if self.context.use_relpaths_for_solc_json else ext_instance.original_file
3081
3105
  for (k, v) in self.asts.items():
3082
- if ext_instance.original_file in v:
3106
+ if orig_path in v:
3083
3107
  build_file_ast = k
3084
3108
  break
3085
3109
  if build_file_ast is None:
@@ -3087,10 +3111,10 @@ class CertoraBuildGenerator:
3087
3111
 
3088
3112
  contract_def_node = self.get_contract_def_node_ref(
3089
3113
  build_file_ast,
3090
- ext_instance.original_file,
3114
+ orig_path,
3091
3115
  storage_ext
3092
3116
  )
3093
- def_node = self.asts[build_file_ast][ext_instance.original_file][contract_def_node]
3117
+ def_node = self.asts[build_file_ast][orig_path][contract_def_node]
3094
3118
  nodes = def_node.get("nodes")
3095
3119
  if not isinstance(nodes, list):
3096
3120
  raise RuntimeError(f"Couldn't find nodes for body of {storage_ext}")
@@ -179,9 +179,12 @@ class CertoraBuildCacheManager:
179
179
  trg = trg_path_with_additional_included_files / post_autofinder_dir.name
180
180
  if post_autofinder_dir != trg:
181
181
  if post_autofinder_dir.is_dir():
182
- if trg.exists():
183
- shutil.rmtree(trg)
184
- Util.safe_copy_folder(post_autofinder_dir, trg, shutil.ignore_patterns())
182
+ # if we match on the cache, and we run a few certoraRun-s in parallel,
183
+ # it could be this folder already exists. But the exact contents do not matter and are likely to
184
+ # agree with the exception of spec files. So let's merge the folders so that the
185
+ # sources are in any case runnable
186
+ if not trg.exists():
187
+ Util.safe_merge_folder(post_autofinder_dir, trg, shutil.ignore_patterns())
185
188
  else:
186
189
  # highly unlikely .post_autofinder.[digit] will be a file and not a directory,
187
190
  # but would rather not crash and future-proof instead
@@ -670,10 +670,10 @@ def get_map_attribute_value(context: CertoraContext, path: Path, attr_name: str)
670
670
  for contract_name, contract_file_path in context.contract_to_file.items():
671
671
  if fnmatch.fnmatch(contract_name, pattern):
672
672
  # Check if this contract's file matches our target path
673
- if Path(contract_file_path) == path:
673
+ if str(path).endswith(contract_file_path):
674
674
  return entry_value
675
675
  else: # This is a file pattern
676
676
  # Match the file pattern against the path
677
677
  if glob.globmatch(str(path), pattern, flags=glob.GLOBSTAR):
678
678
  return entry_value
679
- return None # No match
679
+ raise RuntimeError(f"cannot match {attr_name} to {path} from {attr_name}_map")
@@ -753,6 +753,17 @@ class EvmAttributes(AttrUtil.Attributes):
753
753
  disables_build_cache=True # prefer to be extra careful with this rare option
754
754
  )
755
755
 
756
+ USE_RELPATHS_FOR_SOLC_JSON = AttrUtil.AttributeDefinition(
757
+ arg_type=AttrUtil.AttrArgType.BOOLEAN,
758
+ help_msg="Uses relative paths when constructing json keys for solc's standard-json input",
759
+ default_desc="By using relative paths for the standard json, some rare compilation errors can be prevented",
760
+ argparse_args={
761
+ 'action': AttrUtil.STORE_TRUE
762
+ },
763
+ affects_build_cache_key=True,
764
+ disables_build_cache=False
765
+ )
766
+
756
767
  IGNORE_SOLIDITY_WARNINGS = AttrUtil.AttributeDefinition(
757
768
  arg_type=AttrUtil.AttrArgType.BOOLEAN,
758
769
  help_msg="Ignore all Solidity compiler warnings",
@@ -514,6 +514,18 @@ def safe_copy_folder(source: Path, dest: Path, ignore_patterns: Callable[[str, L
514
514
  shutil.rmtree(copy_temp, ignore_errors=True)
515
515
 
516
516
 
517
+ def safe_merge_folder(source: Path, dest: Path, ignore_patterns: Callable[[str, List[str]], Iterable[str]]) -> None:
518
+ """
519
+ Safely merge source to dest. dest may exist. Will overwrite existing files
520
+ On certain OS/kernels/FS, copying a folder f into a subdirectory of f will
521
+ send copy tree into an infinite loop. This sidesteps the problem by first copying through a temporary folder.
522
+ """
523
+ copy_temp = tempfile.mkdtemp()
524
+ shutil.copytree(source, copy_temp, ignore=ignore_patterns, dirs_exist_ok=True)
525
+ shutil.copytree(copy_temp, dest, dirs_exist_ok=True)
526
+ shutil.rmtree(copy_temp, ignore_errors=True)
527
+
528
+
517
529
  def as_posix(path: str) -> str:
518
530
  """
519
531
  Converts path from windows to unix
@@ -1364,8 +1376,14 @@ def get_mappings_from_forge_remappings() -> List[str]:
1364
1376
  remappings = []
1365
1377
  if remappings_output:
1366
1378
  for line in remappings_output.strip().split('\n'):
1367
- if '=' in line:
1379
+ key, value = line.split('=', 1)
1380
+ if key and value:
1368
1381
  remappings.append(line.strip())
1382
+ for suffix in ['contracts/', 'src/']:
1383
+ if value.endswith(suffix) and not key.endswith(suffix):
1384
+ new_remapping = f"{key}{suffix}={value}"
1385
+ if new_remapping not in remappings:
1386
+ remappings.append(new_remapping)
1369
1387
 
1370
1388
  return remappings
1371
1389
 
@@ -29,6 +29,7 @@ from pathlib import Path
29
29
  from dataclasses import dataclass
30
30
  from rich.console import Console
31
31
  from typing import List, Tuple, Type, Optional, Dict, NoReturn, Callable
32
+ from os import getenv
32
33
 
33
34
  scripts_dir_path = Path(__file__).parent.parent.resolve() # containing directory
34
35
  sys.path.insert(0, str(scripts_dir_path))
@@ -299,6 +300,9 @@ def catch_exits(fn: Callable[..., None]) -> Callable[..., NoReturn]:
299
300
 
300
301
  except Exception as e:
301
302
  console.print(f"[bold red]{e}")
303
+ if getenv('CERTORA_DEV_MODE'):
304
+ import traceback
305
+ console.print(f"Traceback: {traceback.format_exc()}")
302
306
  sys.exit(1)
303
307
 
304
308
  return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: certora-cli-beta-mirror
3
- Version: 8.3.1
3
+ Version: 8.4.1
4
4
  Summary: Runner for the Certora Prover
5
5
  Home-page: https://pypi.org/project/certora-cli-beta-mirror
6
6
  Author: Certora
@@ -39,4 +39,4 @@ Dynamic: requires-dist
39
39
  Dynamic: requires-python
40
40
  Dynamic: summary
41
41
 
42
- Commit 33ef152. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
42
+ Commit 6df223c. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -13,8 +13,8 @@ certora_cli/certoraSorobanProver.py,sha256=SYJKz5Sw-N0bJrSa1njRCE53R9_PMz7IWLhfa
13
13
  certora_cli/rustMutator.py,sha256=6AvOGU8Ijz89zW_ZJCWlfXkeobJsk7EsqZhK7Eqwn-Y,14544
14
14
  certora_cli/CertoraProver/__init__.py,sha256=QHNr-PJQAoyuPgTkO7gg23GRchiWSXglWNG7yLSQZvs,849
15
15
  certora_cli/CertoraProver/certoraApp.py,sha256=RKJ2Krb_CzbRUvczbdE6FhUDrFcvrR8j0JS8MNWXX7s,1469
16
- certora_cli/CertoraProver/certoraBuild.py,sha256=hcZA6lvTFottYU5C9t0KaEKc_jGEIzSEj5u5fotJPPI,225213
17
- certora_cli/CertoraProver/certoraBuildCacheManager.py,sha256=YnZmBZ_gCIbLwExgK5oxFlVDQGe4_YuGIpDLMy589E0,13318
16
+ certora_cli/CertoraProver/certoraBuild.py,sha256=njHHl-D1HLobXk29l5cov9XP2cCAs1xaNSJxBmYx_qw,226911
17
+ certora_cli/CertoraProver/certoraBuildCacheManager.py,sha256=DnVd7w92xjmg0DIrMgoJnCvaU0yCz7ySy0M4RiHEXEM,13648
18
18
  certora_cli/CertoraProver/certoraBuildDataClasses.py,sha256=hO0w3YK9V9gZsTbh4gxxlnEAaOiubUwfzNEw6uL1HaE,14841
19
19
  certora_cli/CertoraProver/certoraBuildRust.py,sha256=ZPbNp4ttRmzcKhFsgHSiHDRExNPaLOzgxTRqu23o1D0,6061
20
20
  certora_cli/CertoraProver/certoraBuildSui.py,sha256=zMXD2XnC4oqRDzPcBvSZmVquL3UG5paBZkfUT3JPbYY,4180
@@ -23,8 +23,8 @@ certora_cli/CertoraProver/certoraCollectConfigurationLayout.py,sha256=Rln6LsqMp-
23
23
  certora_cli/CertoraProver/certoraCollectRunMetadata.py,sha256=i31dkYt8kwlX44SHZtV_b8QI1Egi6cbB5-uuh5beYN0,12630
24
24
  certora_cli/CertoraProver/certoraCompilerParameters.py,sha256=r35y03IRwWIoz1GCNC7PuW3n8JPz9J1NGwhwUYKdYtI,1452
25
25
  certora_cli/CertoraProver/certoraConfigIO.py,sha256=-1EhJYsiheYvyCgOOWrRCQBjqtqNXrpMKJYRq5cKJ0Y,8171
26
- certora_cli/CertoraProver/certoraContext.py,sha256=OVNACUNj9fGb9He8sGdod2waC0eWE8ZgXNPWjRC1lFg,28817
27
- certora_cli/CertoraProver/certoraContextAttributes.py,sha256=dFV44uoKzpfAc5mCcTXVrAR3aFBi1YS_6evWcS5akVA,70197
26
+ certora_cli/CertoraProver/certoraContext.py,sha256=bBbLPet5si6jFEdL1TBORN-HCiJGQK7hD6OQZ_ODmFY,28878
27
+ certora_cli/CertoraProver/certoraContextAttributes.py,sha256=jtL_0nnRbPJ8pMNmMekDHZqTQueQGP_-tOSN6-4ql0Y,70680
28
28
  certora_cli/CertoraProver/certoraContextClass.py,sha256=d7HDqM72K7YnswR7kEcAHGwkFNrTqRz5-_0m7cl2Mso,900
29
29
  certora_cli/CertoraProver/certoraContextValidator.py,sha256=clXwmYHIBUmOJ8ADRUmu9U6_pNe_tXRNawvUPBLlYVY,46490
30
30
  certora_cli/CertoraProver/certoraContractFuncs.py,sha256=-CV7MkmsrwYfdYFAd6ZZib_6-mDG_ytxPM4hAjxtbMM,7137
@@ -65,16 +65,16 @@ certora_cli/Shared/ExpectedComparator.py,sha256=eyRR-jni4WJoa6j2TK2lnZ89Tyb8U99w
65
65
  certora_cli/Shared/__init__.py,sha256=s0dhvolFtsS4sRNzPVhC_rlw8mm194rCZ0WhOxInY40,1025
66
66
  certora_cli/Shared/certoraAttrUtil.py,sha256=Nw8ban5Axp6c6dT-KJfCD9i9tKnGk1DbvRDDNH3--DU,8574
67
67
  certora_cli/Shared/certoraLogging.py,sha256=cV2UQMhQ5j8crGXgeq9CEamI-Lk4HgdiA3HCrP-kSR4,14013
68
- certora_cli/Shared/certoraUtils.py,sha256=wayg6igrwaKi05pqBwAeu0GWFmaTXF8vK8kS_b2GSog,58450
68
+ certora_cli/Shared/certoraUtils.py,sha256=b9qIZ90wW1ofZIlvdFyZRzoVg1HlkA6gfkTaKkVxcQU,59443
69
69
  certora_cli/Shared/certoraValidateFuncs.py,sha256=mYguICGfUwVZ9qPBFajss1xqHPDR-KRtskgERLum4AM,43225
70
- certora_cli/Shared/proverCommon.py,sha256=uZkl9PDLPj81kKRnBnlPUmvhMZovNP25_74No_7jaQ4,11215
71
- certora_jars/ASTExtraction.jar,sha256=-WUqC3U6UHyft5d3qW9FKoYl8IZuSL3D0Q28Et0YrE4,17652496
72
- certora_jars/CERTORA-CLI-VERSION-METADATA.json,sha256=X42-7NRQKFGFXVr_SME0w7ZA4Uw93ZIjVzYT3NCVgnE,142
73
- certora_jars/Typechecker.jar,sha256=SY3njRtjl8HoPVzwc5n6sEx6U9DvW5mdWlEqm4BWbMA,17614653
70
+ certora_cli/Shared/proverCommon.py,sha256=DUB-uEKjOkZ-8qil6xukPqfTynpigXW-gcrm0_kRUZY,11383
71
+ certora_jars/ASTExtraction.jar,sha256=Ng8UDdDV61EIPjBh9-H0646LoeQLA2a5CNCFN3X49o0,20972809
72
+ certora_jars/CERTORA-CLI-VERSION-METADATA.json,sha256=yA1W1HSGmMNq1KsBK40KYMMLzLVdVJJzfvqFC8LyY3w,143
73
+ certora_jars/Typechecker.jar,sha256=_t5VYHpbSKTCtZFYKkNWnvj9LBpGoVEQzHEZr-hPKoQ,20934968
74
74
  certora_jars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- certora_cli_beta_mirror-8.3.1.dist-info/LICENSE,sha256=UGKSKIJSetF8m906JLKqNLkUS2CL60XfQdNvxBvpQXo,620
76
- certora_cli_beta_mirror-8.3.1.dist-info/METADATA,sha256=vSnbSzRa86vjT_SuM9GwISkExJ9IB8KUdzrfV1O8cTw,1286
77
- certora_cli_beta_mirror-8.3.1.dist-info/WHEEL,sha256=9Ig2YBzm5cpS_YWKLeuYxVAxcKv_uDQsCzy9XJbRZ_g,110
78
- certora_cli_beta_mirror-8.3.1.dist-info/entry_points.txt,sha256=ClZiFkCYDdK25_ufxZvnE2Rx_kNk1_4vj7KpgYUKxGM,509
79
- certora_cli_beta_mirror-8.3.1.dist-info/top_level.txt,sha256=8C77w3JLanY0-NW45vpJsjRssyCqVP-qmPiN9FjWiX4,38
80
- certora_cli_beta_mirror-8.3.1.dist-info/RECORD,,
75
+ certora_cli_beta_mirror-8.4.1.dist-info/LICENSE,sha256=UGKSKIJSetF8m906JLKqNLkUS2CL60XfQdNvxBvpQXo,620
76
+ certora_cli_beta_mirror-8.4.1.dist-info/METADATA,sha256=Mr1J2VrDcor8wTtGoMbxriQ541tjfeHXaRPXooRERIA,1286
77
+ certora_cli_beta_mirror-8.4.1.dist-info/WHEEL,sha256=9Ig2YBzm5cpS_YWKLeuYxVAxcKv_uDQsCzy9XJbRZ_g,110
78
+ certora_cli_beta_mirror-8.4.1.dist-info/entry_points.txt,sha256=ClZiFkCYDdK25_ufxZvnE2Rx_kNk1_4vj7KpgYUKxGM,509
79
+ certora_cli_beta_mirror-8.4.1.dist-info/top_level.txt,sha256=8C77w3JLanY0-NW45vpJsjRssyCqVP-qmPiN9FjWiX4,38
80
+ certora_cli_beta_mirror-8.4.1.dist-info/RECORD,,
Binary file
@@ -1 +1 @@
1
- {"name": "certora-cli-beta-mirror", "tag": "8.3.1", "branch": "", "commit": "33ef152", "timestamp": "20251010.9.6.993359", "version": "8.3.1"}
1
+ {"name": "certora-cli-beta-mirror", "tag": "8.4.1", "branch": "", "commit": "6df223c", "timestamp": "20251021.7.13.438699", "version": "8.4.1"}
Binary file