-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
ethervm.py
84 lines (69 loc) · 2.36 KB
/
ethervm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from flask import Flask # type: ignore
from flask_table import Col, Table # type: ignore
from web3.auto.infura.goerli import w3 as goerli_w3
from web3.auto.infura.mainnet import w3 as mainnet_w3
from evm_asm import LATEST_VERSION, disassemble, evm_opcodes
from evm_asm.typing import Bytecode
AVAILABLE_WEB3 = {
"mainnet": mainnet_w3,
"goerli": goerli_w3,
}
app = Flask(__name__)
class OpcodeTable(Table):
opcode_value = Col("Opcode Value")
mnemonic = Col("Mnemonic")
gas_cost = Col("Gas Cost")
input_size_bytes = Col("Input Size (in bytes)")
@app.route("/")
@app.route("/<evm_version>")
def show_table(evm_version: str = LATEST_VERSION.name):
if evm_version not in evm_opcodes.forks():
return ""
opcodes = [
dict(
opcode_value=f"{op.opcode_value:02x}",
mnemonic=mnemonic,
gas_cost=op.gas_cost,
input_size_bytes=op.input_size_bytes,
)
for mnemonic, op in evm_opcodes[evm_version]
]
implemented_opcodes = set(op.opcode_value for _, op in evm_opcodes[evm_version])
opcodes.extend(
[
dict(
opcode_value=f"{opcode_value:02x}",
mnemonic="",
gas_cost="",
input_size_bytes="",
)
for opcode_value in (set(range(256)) - implemented_opcodes)
]
)
def sort_opcodes(opcode):
return opcode["opcode_value"]
opcodes.sort(key=sort_opcodes)
table = OpcodeTable(opcodes)
return table.__html__()
@app.route("/disassemble/<contract_address>")
@app.route("/disassemble/<contract_address>/<network>")
@app.route("/disassemble/<contract_address>/<network>/<evm_version>")
def show_assembly(
contract_address: str,
network: str = "mainnet",
evm_version: str = LATEST_VERSION.name,
):
if network not in AVAILABLE_WEB3:
return "Invalid network"
if evm_version not in evm_opcodes.forks():
return "Not Valid EVM Version"
hexcode = AVAILABLE_WEB3[network].eth.getCode(contract_address)
bytecode = Bytecode(hexcode)
def convert_to_string(o):
if isinstance(o, int):
return f"0x{hex(o)}"
elif isinstance(o, bytes):
return f"0x{o.hex()}"
else:
return str(o)
return "\n".join(convert_to_string(o) for o in disassemble(evm_opcodes[evm_version], bytecode))