Skip to content

Commit 6333cd8

Browse files
committed
prepare_report.py: Add --force-no-optimize-yul flag to work around a bug in solc 0.6.0/0.6.1
1 parent a3e0ba0 commit 6333cd8

File tree

2 files changed

+72
-8
lines changed

2 files changed

+72
-8
lines changed

scripts/bytecodecompare/prepare_report.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
from typing import List, Optional, Tuple, Union
1414

1515

16-
CONTRACT_SEPARATOR_PATTERN = re.compile(r'^ *======= +(?:(?P<file_name>.+) *:)? *(?P<contract_name>[^:]+) +======= *$', re.MULTILINE)
16+
CONTRACT_SEPARATOR_PATTERN = re.compile(
17+
r'^ *======= +(?:(?P<file_name>.+) *:)? *(?P<contract_name>[^:]+) +======= *$',
18+
re.MULTILINE
19+
)
1720
BYTECODE_REGEX = re.compile(r'^ *Binary: *\n(?P<bytecode>.*[0-9a-f$_]+.*)$', re.MULTILINE)
1821
METADATA_REGEX = re.compile(r'^ *Metadata: *\n *(?P<metadata>\{.*\}) *$', re.MULTILINE)
1922

@@ -134,13 +137,15 @@ def parse_cli_output(source_file_name: Path, cli_output: str) -> FileReport:
134137
return file_report
135138

136139

137-
def prepare_compiler_input(
140+
def prepare_compiler_input( # pylint: disable=too-many-arguments
138141
compiler_path: Path,
139142
source_file_name: Path,
140143
optimize: bool,
144+
force_no_optimize_yul: bool,
141145
interface: CompilerInterface,
142-
smt_use: SMTUse
146+
smt_use: SMTUse,
143147
) -> Tuple[List[str], str]:
148+
144149
if interface == CompilerInterface.STANDARD_JSON:
145150
json_input: dict = {
146151
'language': 'Solidity',
@@ -164,6 +169,8 @@ def prepare_compiler_input(
164169
compiler_options = [str(source_file_name), '--bin', '--metadata']
165170
if optimize:
166171
compiler_options.append('--optimize')
172+
elif force_no_optimize_yul:
173+
compiler_options.append('--no-optimize-yul')
167174
if smt_use == SMTUse.DISABLE:
168175
compiler_options += ['--model-checker-engine', 'none']
169176

@@ -173,20 +180,22 @@ def prepare_compiler_input(
173180
return (command_line, compiler_input)
174181

175182

176-
def run_compiler(
183+
def run_compiler( # pylint: disable=too-many-arguments
177184
compiler_path: Path,
178185
source_file_name: Path,
179186
optimize: bool,
187+
force_no_optimize_yul: bool,
180188
interface: CompilerInterface,
181189
smt_use: SMTUse,
182190
tmp_dir: Path
183-
) -> FileReport: # pylint: disable=too-many-arguments
191+
) -> FileReport:
184192

185193
if interface == CompilerInterface.STANDARD_JSON:
186194
(command_line, compiler_input) = prepare_compiler_input(
187195
compiler_path,
188196
Path(Path(source_file_name).name),
189197
optimize,
198+
force_no_optimize_yul,
190199
interface,
191200
smt_use,
192201
)
@@ -208,6 +217,7 @@ def run_compiler(
208217
compiler_path.absolute(),
209218
Path(source_file_name.name),
210219
optimize,
220+
force_no_optimize_yul,
211221
interface,
212222
smt_use,
213223
)
@@ -228,7 +238,13 @@ def run_compiler(
228238
return parse_cli_output(Path(source_file_name), process.stdout)
229239

230240

231-
def generate_report(source_file_names: List[str], compiler_path: Path, interface: CompilerInterface, smt_use: SMTUse):
241+
def generate_report(
242+
source_file_names: List[str],
243+
compiler_path: Path,
244+
interface: CompilerInterface,
245+
smt_use: SMTUse,
246+
force_no_optimize_yul: bool
247+
):
232248
with open('report.txt', mode='w', encoding='utf8', newline='\n') as report_file:
233249
for optimize in [False, True]:
234250
with TemporaryDirectory(prefix='prepare_report-') as tmp_dir:
@@ -238,6 +254,7 @@ def generate_report(source_file_names: List[str], compiler_path: Path, interface
238254
Path(compiler_path),
239255
Path(source_file_name),
240256
optimize,
257+
force_no_optimize_yul,
241258
interface,
242259
smt_use,
243260
Path(tmp_dir)
@@ -283,6 +300,13 @@ def commandline_parser() -> ArgumentParser:
283300
choices=[s.value for s in SMTUse],
284301
help="What to do about contracts that use the experimental SMT checker."
285302
)
303+
parser.add_argument(
304+
'--force-no-optimize-yul',
305+
dest='force_no_optimize_yul',
306+
default=False,
307+
action='store_true',
308+
help="Explicitly disable Yul optimizer in CLI runs without optimization to work around a bug in solc 0.6.0 and 0.6.1."
309+
)
286310
return parser;
287311

288312

@@ -293,4 +317,5 @@ def commandline_parser() -> ArgumentParser:
293317
Path(options.compiler_path),
294318
CompilerInterface(options.interface),
295319
SMTUse(options.smt_use),
320+
options.force_no_optimize_yul,
296321
)

test/scripts/test_bytecodecompare_prepare_report.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def test_format_report_should_not_print_anything_if_contract_report_list_is_empt
9191
self.assertEqual(report.format_report(), '')
9292

9393

94-
class TestPrepareReport(unittest.TestCase):
94+
class TestPrepareReport_LoadSource(unittest.TestCase):
9595
def setUp(self):
9696
self.maxDiff = 10000
9797

@@ -108,6 +108,11 @@ def test_load_source_should_not_strip_smt_pragmas_if_not_requested(self):
108108
self.assertEqual(load_source(SMT_SMOKE_TEST_SOL_PATH, SMTUse.DISABLE), SMT_SMOKE_TEST_SOL_CODE)
109109
self.assertEqual(load_source(SMT_SMOKE_TEST_SOL_PATH, SMTUse.PRESERVE), SMT_SMOKE_TEST_SOL_CODE)
110110

111+
112+
class TestPrepareReport_PrepareCompilerInput(unittest.TestCase):
113+
def setUp(self):
114+
self.maxDiff = 10000
115+
111116
def test_prepare_compiler_input_should_work_with_standard_json_interface(self):
112117
expected_compiler_input = {
113118
'language': 'Solidity',
@@ -125,6 +130,7 @@ def test_prepare_compiler_input_should_work_with_standard_json_interface(self):
125130
Path('solc'),
126131
SMT_SMOKE_TEST_SOL_PATH,
127132
optimize=True,
133+
force_no_optimize_yul=False,
128134
interface=CompilerInterface.STANDARD_JSON,
129135
smt_use=SMTUse.DISABLE
130136
)
@@ -137,6 +143,7 @@ def test_prepare_compiler_input_should_work_with_cli_interface(self):
137143
Path('solc'),
138144
SMT_SMOKE_TEST_SOL_PATH,
139145
optimize=True,
146+
force_no_optimize_yul=False,
140147
interface=CompilerInterface.CLI,
141148
smt_use=SMTUse.DISABLE
142149
)
@@ -147,6 +154,27 @@ def test_prepare_compiler_input_should_work_with_cli_interface(self):
147154
)
148155
self.assertEqual(compiler_input, SMT_SMOKE_TEST_SOL_CODE)
149156

157+
def test_prepare_compiler_input_should_handle_force_no_optimize_yul_flag(self):
158+
(command_line, compiler_input) = prepare_compiler_input(
159+
Path('solc'),
160+
SMT_SMOKE_TEST_SOL_PATH,
161+
optimize=False,
162+
force_no_optimize_yul=True,
163+
interface=CompilerInterface.CLI,
164+
smt_use=SMTUse.DISABLE
165+
)
166+
167+
self.assertEqual(
168+
command_line,
169+
['solc', str(SMT_SMOKE_TEST_SOL_PATH), '--bin', '--metadata', '--no-optimize-yul', '--model-checker-engine', 'none'],
170+
)
171+
self.assertEqual(compiler_input, SMT_SMOKE_TEST_SOL_CODE)
172+
173+
174+
class TestPrepareReport_ParseStandardJSONOutput(unittest.TestCase):
175+
def setUp(self):
176+
self.maxDiff = 10000
177+
150178
def test_parse_standard_json_output(self):
151179
expected_report = FileReport(
152180
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
@@ -272,6 +300,11 @@ def test_parse_standard_json_output_should_report_missing_if_value_is_just_white
272300

273301
self.assertEqual(parse_standard_json_output(Path('contract.sol'), compiler_output), expected_report)
274302

303+
304+
class TestPrepareReport_ParseCLIOutput(unittest.TestCase):
305+
def setUp(self):
306+
self.maxDiff = 10000
307+
275308
def test_parse_cli_output(self):
276309
expected_report = FileReport(
277310
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
@@ -389,12 +422,14 @@ def test_parse_cli_output_should_handle_output_from_solc_0_4_8(self):
389422
expected_report = FileReport(
390423
file_name=Path('contract.sol'),
391424
contract_reports=[
425+
# pragma pylint: disable=line-too-long
392426
ContractReport(
393427
contract_name='C',
394428
file_name=None,
395429
bytecode='6060604052346000575b60358060166000396000f30060606040525b60005600a165627a7a72305820ccf9337430b4c4f7d6ad41efb10a94411a2af6a9f173ef52daeadd31f4bf11890029',
396430
metadata='{"compiler":{"version":"0.4.8+commit.60cc1668.mod.Darwin.appleclang"},"language":"Solidity","output":{"abi":[],"devdoc":{"methods":{}},"userdoc":{"methods":{}}},"settings":{"compilationTarget":{"contract.sol":"C"},"libraries":{},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"contract.sol":{"keccak256":"0xbe86d3681a198587296ad6d4a834606197e1a8f8944922c501631b04e21eeba2","urls":["bzzr://af16957d3d86013309d64d3cc572d007b1d8b08a821f2ff366840deb54a78524"]}},"version":1}',
397431
)
432+
# pragma pylint: enable=line-too-long
398433
]
399434
)
400435

@@ -411,7 +446,9 @@ def test_parse_cli_output_should_handle_leading_and_trailing_spaces(self):
411446

412447
expected_report = FileReport(
413448
file_name=Path('contract.sol'),
414-
contract_reports=[ContractReport(contract_name='C', file_name=Path('contract.sol'), bytecode='60806040523480156', metadata='{ }')]
449+
contract_reports=[
450+
ContractReport(contract_name='C', file_name=Path('contract.sol'), bytecode='60806040523480156', metadata='{ }')
451+
]
415452
)
416453

417454
self.assertEqual(parse_cli_output(Path('contract.sol'), compiler_output), expected_report)
@@ -460,12 +497,14 @@ def test_parse_cli_output_should_handle_link_references_in_bytecode(self):
460497
__$fb58009a6b1ecea3b9d99bedd645df4ec3$__
461498
""")
462499

500+
# pragma pylint: disable=line-too-long
463501
expected_report = FileReport(
464502
file_name=Path('contract.sol'),
465503
contract_reports=[
466504
ContractReport(contract_name='C', file_name=Path('contract.sol'), bytecode='73123456789012345678901234567890123456789073__$fb58009a6b1ecea3b9d99bedd645df4ec3$__5050', metadata=None),
467505
ContractReport(contract_name='D', file_name=Path('contract.sol'), bytecode='__$fb58009a6b1ecea3b9d99bedd645df4ec3$__', metadata=None),
468506
]
469507
)
508+
# pragma pylint: enable=line-too-long
470509

471510
self.assertEqual(parse_cli_output(Path('contract.sol'), compiler_output), expected_report)

0 commit comments

Comments
 (0)