certora-cli 7.0.7__tar.gz → 7.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {certora-cli-7.0.7/certora_cli.egg-info → certora-cli-7.3.0}/PKG-INFO +2 -2
- certora-cli-7.3.0/README.md +1 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +24 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +8 -2
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +29 -17
- certora-cli-7.3.0/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +21 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +12 -0
- certora-cli-7.3.0/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +90 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraBuild.py +144 -165
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContext.py +18 -11
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextAttribute.py +69 -26
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextValidator.py +36 -13
- certora-cli-7.3.0/certora_cli/EVMVerifier/certoraContractFuncs.py +121 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Mutate/mutateApp.py +78 -16
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Mutate/mutateAttribute.py +15 -3
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Mutate/mutateConstants.py +7 -1
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/certoraAttrUtil.py +12 -6
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/certoraUtils.py +48 -14
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/certoraValidateFuncs.py +14 -7
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/certoraMutate.py +23 -10
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/certoraRun.py +3 -8
- {certora-cli-7.0.7 → certora-cli-7.3.0/certora_cli.egg-info}/PKG-INFO +2 -2
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli.egg-info/SOURCES.txt +3 -0
- certora-cli-7.3.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_jars/Typechecker.jar +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/setup.py +2 -2
- certora-cli-7.0.7/README.md +0 -1
- certora-cli-7.0.7/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora-cli-7.0.7 → certora-cli-7.3.0}/LICENSE +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/MANIFEST.in +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_bins/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraCloudIO.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraCompilerParameters.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraConfigIO.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/certoraType.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Mutate/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Mutate/mutateValidate.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/certoraEqCheck.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli.egg-info/entry_points.txt +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli.egg-info/requires.txt +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli.egg-info/top_level.txt +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/certora_jars/__init__.py +0 -0
- {certora-cli-7.0.7 → certora-cli-7.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.3.0
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli
|
|
6
6
|
Author: Certora
|
|
@@ -21,4 +21,4 @@ Requires-Dist: tabulate
|
|
|
21
21
|
Requires-Dist: tqdm
|
|
22
22
|
Requires-Dist: StrEnum
|
|
23
23
|
|
|
24
|
-
Commit
|
|
24
|
+
Commit 3dce873. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 3dce873. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
{certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py
RENAMED
|
@@ -131,6 +131,30 @@ class CompilerLang(metaclass=AbstractAndSingleton):
|
|
|
131
131
|
"""
|
|
132
132
|
pass
|
|
133
133
|
|
|
134
|
+
@property
|
|
135
|
+
@abstractmethod
|
|
136
|
+
def supports_typed_immutables(self) -> bool:
|
|
137
|
+
"""
|
|
138
|
+
:return: True if has type information associated to immutables
|
|
139
|
+
"""
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
@abstractmethod
|
|
144
|
+
def supports_ast_output(self) -> bool:
|
|
145
|
+
"""
|
|
146
|
+
:return: True if compiling contracts in this language produces AST output
|
|
147
|
+
"""
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
@abstractmethod
|
|
152
|
+
def supports_srclist_output(self) -> bool:
|
|
153
|
+
"""
|
|
154
|
+
:return: True if compiling contracts in this language produces srclist output
|
|
155
|
+
"""
|
|
156
|
+
pass
|
|
157
|
+
|
|
134
158
|
|
|
135
159
|
class CompilerCollector(ABC):
|
|
136
160
|
"""
|
{certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py
RENAMED
|
@@ -9,6 +9,7 @@ import re
|
|
|
9
9
|
import logging
|
|
10
10
|
from EVMVerifier.Compiler.CompilerCollector import CompilerLang, CompilerCollector
|
|
11
11
|
from EVMVerifier.Compiler.CompilerCollectorSol import CompilerCollectorSol, CompilerLangSol
|
|
12
|
+
from EVMVerifier.Compiler.CompilerCollectorYul import CompilerLangYul, CompilerCollectorYul
|
|
12
13
|
from EVMVerifier.Compiler.CompilerCollectorVy import CompilerCollectorVy, CompilerLangVy
|
|
13
14
|
from Shared.certoraUtils import is_windows, match_path_to_mapping_key, remove_file, get_certora_config_dir
|
|
14
15
|
from EVMVerifier.certoraContextClass import CertoraContext
|
|
@@ -71,9 +72,12 @@ class CompilerCollectorFactory:
|
|
|
71
72
|
return CompilerCollectorVy(version)
|
|
72
73
|
elif str(path).endswith(".sol"):
|
|
73
74
|
version = self.__get_solc_version(path)
|
|
74
|
-
return CompilerCollectorSol(version)
|
|
75
|
+
return CompilerCollectorSol(version, CompilerLangSol(), self.context.use_memory_safe_autofinders)
|
|
76
|
+
elif str(path).endswith(".yul"):
|
|
77
|
+
version = self.__get_solc_version(path)
|
|
78
|
+
return CompilerCollectorYul(version, CompilerLangYul())
|
|
75
79
|
else:
|
|
76
|
-
raise RuntimeError(f'expected {path} to represent a Solidity or Vyper file')
|
|
80
|
+
raise RuntimeError(f'expected {path} to represent a Solidity, Yul, or Vyper file')
|
|
77
81
|
|
|
78
82
|
@staticmethod
|
|
79
83
|
def get_vyper_compiler(contract_file_path: Path, default_compiler: str, compiler_mappings: Dict[str, str]) -> str:
|
|
@@ -170,5 +174,7 @@ def get_compiler_lang(file_name: str) -> CompilerLang:
|
|
|
170
174
|
return CompilerLangVy()
|
|
171
175
|
elif file_name.endswith(".sol"):
|
|
172
176
|
return CompilerLangSol()
|
|
177
|
+
elif file_name.endswith(".yul"):
|
|
178
|
+
return CompilerLangYul()
|
|
173
179
|
else:
|
|
174
180
|
raise RuntimeError(f'expected {file_name} to represent a Solidity or Vyper file')
|
{certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Any, List, Tuple, Dict, Set
|
|
3
3
|
|
|
4
|
-
from EVMVerifier.Compiler.CompilerCollector import CompilerLang,
|
|
4
|
+
from EVMVerifier.Compiler.CompilerCollector import CompilerLang, CompilerLangFunc
|
|
5
|
+
from EVMVerifier.Compiler.CompilerCollectorSolBased import CompilerCollectorSolBased
|
|
5
6
|
from Shared.certoraUtils import Singleton, CompilerVersion, get_certora_config_dir
|
|
6
7
|
import EVMVerifier.certoraType as CT
|
|
7
8
|
|
|
@@ -62,33 +63,44 @@ class CompilerLangSol(CompilerLang, metaclass=Singleton):
|
|
|
62
63
|
Tuple[List[CT.Type], List[CompilerLangFunc]]:
|
|
63
64
|
assert False, "collect_source_type_descriptions() has not yet been implemented in CompilerLangSol"
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
# This class is intended for calculations of compiler-settings related queries
|
|
67
|
-
class CompilerCollectorSol(CompilerCollector):
|
|
68
|
-
|
|
69
|
-
def __init__(self, version: CompilerVersion):
|
|
70
|
-
self.__compiler_version = version
|
|
71
|
-
|
|
72
66
|
@property
|
|
73
|
-
def
|
|
74
|
-
return
|
|
67
|
+
def supports_typed_immutables(self) -> bool:
|
|
68
|
+
return True
|
|
75
69
|
|
|
76
70
|
@property
|
|
77
|
-
def
|
|
78
|
-
return
|
|
71
|
+
def supports_ast_output(self) -> bool:
|
|
72
|
+
return True
|
|
79
73
|
|
|
80
74
|
@property
|
|
81
|
-
def
|
|
82
|
-
return
|
|
75
|
+
def supports_srclist_output(self) -> bool:
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# This class is intended for calculations of compiler-settings related queries
|
|
80
|
+
class CompilerCollectorSol(CompilerCollectorSolBased):
|
|
81
|
+
|
|
82
|
+
def __init__(self, version: CompilerVersion, lang: CompilerLang, use_memory_safe_autofinders: bool):
|
|
83
|
+
super().__init__(version, lang)
|
|
84
|
+
self.__use_memory_safe_autofinders = use_memory_safe_autofinders
|
|
83
85
|
|
|
84
86
|
def normalize_storage(self, is_storage: bool, arg_name: str) -> str:
|
|
85
87
|
if not is_storage:
|
|
86
88
|
return arg_name
|
|
87
|
-
if self.
|
|
89
|
+
if self.compiler_version[0] == 0 and self.compiler_version[1] < 7:
|
|
88
90
|
return arg_name + "_slot"
|
|
89
91
|
else:
|
|
90
92
|
return arg_name + ".slot"
|
|
91
93
|
|
|
92
94
|
def supports_calldata_assembly(self, arg_name: str) -> bool:
|
|
93
|
-
return (self.
|
|
94
|
-
self.
|
|
95
|
+
return (self.compiler_version[1] > 7 or (
|
|
96
|
+
self.compiler_version[1] == 7 and self.compiler_version[2] >= 5)) and arg_name != ""
|
|
97
|
+
|
|
98
|
+
def supports_memory_safe_assembly(self) -> bool:
|
|
99
|
+
return (self.compiler_version[1] > 8 or (
|
|
100
|
+
self.compiler_version[1] == 8 and self.compiler_version[2] >= 13))
|
|
101
|
+
|
|
102
|
+
def gen_memory_safe_assembly_prefix(self) -> str:
|
|
103
|
+
if self.supports_memory_safe_assembly() and self.__use_memory_safe_autofinders:
|
|
104
|
+
return 'assembly ("memory-safe")'
|
|
105
|
+
else:
|
|
106
|
+
return 'assembly'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from EVMVerifier.Compiler.CompilerCollector import CompilerCollector, CompilerLang
|
|
2
|
+
from Shared.certoraUtils import CompilerVersion
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CompilerCollectorSolBased(CompilerCollector):
|
|
6
|
+
|
|
7
|
+
def __init__(self, version: CompilerVersion, lang: CompilerLang):
|
|
8
|
+
self.__compiler_version = version
|
|
9
|
+
self.__smart_contract_lang = lang
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def compiler_name(self) -> str:
|
|
13
|
+
return self.smart_contract_lang.compiler_name
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def smart_contract_lang(self) -> CompilerLang:
|
|
17
|
+
return self.__smart_contract_lang
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def compiler_version(self) -> CompilerVersion:
|
|
21
|
+
return self.__compiler_version
|
{certora-cli-7.0.7 → certora-cli-7.3.0}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py
RENAMED
|
@@ -491,6 +491,18 @@ class CompilerLangVy(CompilerLang, metaclass=Singleton):
|
|
|
491
491
|
|
|
492
492
|
vyper_constructor_name = "__init__"
|
|
493
493
|
|
|
494
|
+
@property
|
|
495
|
+
def supports_typed_immutables(self) -> bool:
|
|
496
|
+
return True
|
|
497
|
+
|
|
498
|
+
@property
|
|
499
|
+
def supports_ast_output(self) -> bool:
|
|
500
|
+
return True
|
|
501
|
+
|
|
502
|
+
@property
|
|
503
|
+
def supports_srclist_output(self) -> bool:
|
|
504
|
+
return True
|
|
505
|
+
|
|
494
506
|
@staticmethod
|
|
495
507
|
def extract_constant(ast_node: Dict[str, Any], named_constants: Dict[str, int]) -> int:
|
|
496
508
|
"""
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from Crypto.Hash import keccak
|
|
5
|
+
|
|
6
|
+
from EVMVerifier.Compiler.CompilerCollector import CompilerLang
|
|
7
|
+
from EVMVerifier.Compiler.CompilerCollectorSol import CompilerLangSol
|
|
8
|
+
from EVMVerifier.Compiler.CompilerCollectorSolBased import CompilerCollectorSolBased
|
|
9
|
+
from EVMVerifier.certoraContractFuncs import Func
|
|
10
|
+
from Shared.certoraUtils import Singleton, CompilerVersion
|
|
11
|
+
import EVMVerifier.certoraType as CT
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CompilerLangYul(CompilerLangSol, metaclass=Singleton):
|
|
15
|
+
"""
|
|
16
|
+
[CompilerLang] for Yul
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def name(self) -> str:
|
|
21
|
+
return "Yul"
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def supports_typed_immutables(self) -> bool:
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def supports_ast_output(self) -> bool:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def supports_srclist_output(self) -> bool:
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def get_sighash(name: str, full_args: List[CT.TypeInstance]) -> str:
|
|
37
|
+
sig = Func.compute_signature(name, full_args, lambda x: x.get_source_str())
|
|
38
|
+
f_hash = keccak.new(digest_bits=256)
|
|
39
|
+
f_hash.update(str.encode(sig))
|
|
40
|
+
|
|
41
|
+
return f_hash.hexdigest()[0:8]
|
|
42
|
+
|
|
43
|
+
def get_funcs(self, yul_abi_json_filepath: str, contract_name: str) -> List[Func]:
|
|
44
|
+
funcs = []
|
|
45
|
+
with open(yul_abi_json_filepath, 'r') as yul_abi_json_file:
|
|
46
|
+
yul_abi_json = json.load(yul_abi_json_file)
|
|
47
|
+
for entry in yul_abi_json:
|
|
48
|
+
if "type" in entry and entry["type"] == "function":
|
|
49
|
+
name = entry["name"]
|
|
50
|
+
state_mutability = entry["stateMutability"]
|
|
51
|
+
full_args = []
|
|
52
|
+
param_names = []
|
|
53
|
+
for input in entry["inputs"]:
|
|
54
|
+
type_name = input["type"]
|
|
55
|
+
# yul abi is annoying. no better way
|
|
56
|
+
if type_name.endswith("[]"):
|
|
57
|
+
base = type_name[:-2]
|
|
58
|
+
base_type = CT.Type.from_primitive_name(base)
|
|
59
|
+
out_type: CT.Type = CT.ArrayType(type_name, base_type, None, contract_name, 0)
|
|
60
|
+
elif type_name == "bytes":
|
|
61
|
+
out_type = CT.PackedBytes()
|
|
62
|
+
else:
|
|
63
|
+
out_type = CT.Type.from_primitive_name(input["type"])
|
|
64
|
+
full_args.append(CT.TypeInstance(out_type))
|
|
65
|
+
param_names.append(input["name"])
|
|
66
|
+
returns = []
|
|
67
|
+
for output in entry["outputs"]:
|
|
68
|
+
type_name = output["type"]
|
|
69
|
+
# yul abi is annoying. no better way
|
|
70
|
+
if type_name.endswith("[]"):
|
|
71
|
+
base = type_name[:-2]
|
|
72
|
+
base_type = CT.Type.from_primitive_name(base)
|
|
73
|
+
out_type = CT.ArrayType(type_name, base_type, None, contract_name, 0)
|
|
74
|
+
elif type_name == "bytes":
|
|
75
|
+
out_type = CT.PackedBytes()
|
|
76
|
+
else:
|
|
77
|
+
out_type = CT.Type.from_primitive_name(output["type"])
|
|
78
|
+
returns.append(CT.TypeInstance(out_type))
|
|
79
|
+
visibility = "external"
|
|
80
|
+
sighash = self.get_sighash(name, full_args)
|
|
81
|
+
notpayable = state_mutability in ["nonpayable", "view", "pure"]
|
|
82
|
+
|
|
83
|
+
funcs.append(Func(name, full_args, param_names, returns, sighash, notpayable, False, False,
|
|
84
|
+
state_mutability, visibility, True, False, contract_name, None, None))
|
|
85
|
+
return funcs
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class CompilerCollectorYul(CompilerCollectorSolBased):
|
|
89
|
+
def __init__(self, version: CompilerVersion, lang: CompilerLang):
|
|
90
|
+
super().__init__(version, lang)
|