Skip to content

Instantly share code, notes, and snippets.

@spalladino

spalladino/guess.py

Created Jan 29, 2020
Embed
What would you like to do?
Guess solc settings used to compile a given contract
#!/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
You can’t perform that action at this time.