Created
January 29, 2020 21:41
-
-
Save spalladino/3c27d8d9c90d8a9566d11091165a87c1 to your computer and use it in GitHub Desktop.
Guess solc settings used to compile a given contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import json | |
import subprocess | |
import sys | |
import re | |
VERSIONS = [f'0.5.{minor}' for minor in range(0,16)] | |
RUNS = [0, 100, 200, 300] | |
TARGETS = ['byzantium', 'constantinople', 'petersburg', 'istanbul'] | |
OPTIMIZERS = [False, True] | |
def guess(contractname, expected): | |
for version in VERSIONS: | |
for target in TARGETS: | |
for optimizer in OPTIMIZERS: | |
for runs in (RUNS if optimizer else [0]): | |
result = compile(contractname, version, target, optimizer, runs) | |
if result: | |
if check(result, expected): | |
log(version, target, optimizer, runs, "MATCH FOUND") | |
return (version, target, optimizer, runs) | |
else: log(version, target, optimizer, runs, "NO MATCH") | |
def compile(contractname, version, target, optimizer, runs): | |
optimizerstr = "on" if optimizer else "off" | |
result = subprocess.run([ | |
"openzeppelin", "compile", | |
"--solc-version", str(version), | |
"--optimizer", optimizerstr, | |
"--optimizer-runs", str(runs), | |
"--evm-version", target, | |
"--no-interactive"], shell=False) | |
if result.returncode != 0: | |
log(version, target, optimizer, runs, "COMPILATION FAILED") | |
return | |
with open(f'build/contracts/{contractname}.json') as artifactfile: | |
artifact = json.load(artifactfile) | |
return artifact['deployedBytecode'] | |
def check(result, expected): | |
return removemetadata(result) == removemetadata(expected) | |
def removemetadata(bytecode): | |
length = int(bytecode[-4:], 16) * 2 | |
return bytecode[:-length] | |
def log(version, target, optimizer, runs, log): | |
print(f'version={version} target={target} optimizer={optimizer} runs={runs} | {log}') | |
if __name__ == "__main__": | |
if len(sys.argv) < 3: | |
print("Usage: python3 guess.py CONTRACTNAME BYTECODE_OR_PATH_TO_BYTECODE") | |
else: | |
contractname = sys.argv[1] | |
expected = sys.argv[2] | |
if expected[:2] != '0x': | |
with open(expected) as f: | |
expected = f.read().strip() | |
if expected[:2] != '0x': | |
raise Exception("Expected bytecode to start with 0x") | |
if not re.match("\A0x[a-f0-9]+\Z", expected): | |
raise Exception("Non-hex character in expected bytecode") | |
guess(contractname, expected) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment