mirror of https://github.com/ConsenSys/mythril
Refactor opcode files and fix issues (#1532)
parent
579480b477
commit
9d922fe9f4
@ -1,100 +1,144 @@ |
||||
# This pyethereum opcodes file with added opcodes |
||||
from typing import Dict, Tuple |
||||
from typing import Dict, Tuple, Union |
||||
|
||||
opcodes = { |
||||
0x00: ("STOP", 0, 0, 0), |
||||
0x01: ("ADD", 2, 1, 3), |
||||
0x02: ("MUL", 2, 1, 5), |
||||
0x03: ("SUB", 2, 1, 3), |
||||
0x04: ("DIV", 2, 1, 5), |
||||
0x05: ("SDIV", 2, 1, 5), |
||||
0x06: ("MOD", 2, 1, 5), |
||||
0x07: ("SMOD", 2, 1, 5), |
||||
0x08: ("ADDMOD", 3, 1, 8), |
||||
0x09: ("MULMOD", 3, 1, 8), |
||||
0x0A: ("EXP", 2, 1, 10), |
||||
0x0B: ("SIGNEXTEND", 2, 1, 5), |
||||
0x10: ("LT", 2, 1, 3), |
||||
0x11: ("GT", 2, 1, 3), |
||||
0x12: ("SLT", 2, 1, 3), |
||||
0x13: ("SGT", 2, 1, 3), |
||||
0x14: ("EQ", 2, 1, 3), |
||||
0x15: ("ISZERO", 1, 1, 3), |
||||
0x16: ("AND", 2, 1, 3), |
||||
0x17: ("OR", 2, 1, 3), |
||||
0x18: ("XOR", 2, 1, 3), |
||||
0x19: ("NOT", 1, 1, 3), |
||||
0x1A: ("BYTE", 2, 1, 3), |
||||
0x1B: ("SHL", 2, 1, 3), |
||||
0x1C: ("SHR", 2, 1, 3), |
||||
0x1D: ("SAR", 2, 1, 3), |
||||
0x20: ("SHA3", 2, 1, 30), |
||||
0x30: ("ADDRESS", 0, 1, 2), |
||||
0x31: ("BALANCE", 1, 1, 20), # now 400 |
||||
0x32: ("ORIGIN", 0, 1, 2), |
||||
0x33: ("CALLER", 0, 1, 2), |
||||
0x34: ("CALLVALUE", 0, 1, 2), |
||||
0x35: ("CALLDATALOAD", 1, 1, 3), |
||||
0x36: ("CALLDATASIZE", 0, 1, 2), |
||||
0x37: ("CALLDATACOPY", 3, 0, 3), |
||||
0x38: ("CODESIZE", 0, 1, 2), |
||||
0x39: ("CODECOPY", 3, 0, 3), |
||||
0x3A: ("GASPRICE", 0, 1, 2), |
||||
0x3B: ("EXTCODESIZE", 1, 1, 20), # now 700 |
||||
0x3C: ("EXTCODECOPY", 4, 0, 20), # now 700 |
||||
0x3D: ("RETURNDATASIZE", 0, 1, 2), |
||||
0x3E: ("RETURNDATACOPY", 3, 0, 3), |
||||
0x3F: ("EXTCODEHASH", 3, 0, 3), |
||||
0x40: ("BLOCKHASH", 1, 1, 20), |
||||
0x41: ("COINBASE", 0, 1, 2), |
||||
0x42: ("TIMESTAMP", 0, 1, 2), |
||||
0x43: ("NUMBER", 0, 1, 2), |
||||
0x44: ("DIFFICULTY", 0, 1, 2), |
||||
0x45: ("GASLIMIT", 0, 1, 2), |
||||
0x46: ("CHAINID", 0, 1, 2), |
||||
0x47: ("SELFBALANCE", 0, 1, 5), |
||||
0x48: ("BASEFEE", 0, 1, 2), |
||||
0x50: ("POP", 1, 0, 2), |
||||
0x51: ("MLOAD", 1, 1, 3), |
||||
0x52: ("MSTORE", 2, 0, 3), |
||||
0x53: ("MSTORE8", 2, 0, 3), |
||||
0x54: ("SLOAD", 1, 1, 50), # 200 now |
||||
0x55: ("SSTORE", 2, 0, 0), |
||||
0x56: ("JUMP", 1, 0, 8), |
||||
0x57: ("JUMPI", 2, 0, 10), |
||||
0x58: ("PC", 0, 1, 2), |
||||
0x59: ("MSIZE", 0, 1, 2), |
||||
0x5A: ("GAS", 0, 1, 2), |
||||
0x5B: ("JUMPDEST", 0, 0, 1), |
||||
0x5C: ("BEGINSUB", 0, 0, 2), |
||||
0x5D: ("RETURNSUB", 0, 0, 5), |
||||
0x5E: ("JUMPSUB", 1, 0, 10), |
||||
0xA0: ("LOG0", 2, 0, 375), |
||||
0xA1: ("LOG1", 3, 0, 750), |
||||
0xA2: ("LOG2", 4, 0, 1125), |
||||
0xA3: ("LOG3", 5, 0, 1500), |
||||
0xA4: ("LOG4", 6, 0, 1875), |
||||
0xF0: ("CREATE", 3, 1, 32000), |
||||
0xF1: ("CALL", 7, 1, 40), # 700 now |
||||
0xF2: ("CALLCODE", 7, 1, 40), # 700 now |
||||
0xF3: ("RETURN", 2, 0, 0), |
||||
0xF4: ("DELEGATECALL", 6, 1, 40), # 700 now |
||||
0xF5: ("CREATE2", 3, 1, 32000), |
||||
0xFA: ("STATICCALL", 6, 1, 40), |
||||
0xFD: ("REVERT", 2, 0, 0), |
||||
0xFF: ("SUICIDE", 1, 0, 0), # 5000 now |
||||
} # type: Dict[int, Tuple[str, int, int, int]] |
||||
|
||||
opcodesMetropolis = {0x3D, 0x3E, 0xFA, 0xFD} |
||||
Z_OPERATOR_TUPLE = (0, 1) |
||||
UN_OPERATOR_TUPLE = (1, 1) |
||||
BIN_OPERATOR_TUPLE = (2, 1) |
||||
T_OPERATOR_TUPLE = (3, 1) |
||||
GAS = "gas" |
||||
STACK = "stack" |
||||
ADDRESS = "address" |
||||
|
||||
# Gas tuple contains (min_gas, max_gas) |
||||
# stack tuple contains (no_of_elements_popped, no_of_elements_pushed) |
||||
|
||||
# TODO: Make this more specific when TypedDict supports key re-usage. |
||||
OPCODES: Dict = { |
||||
"STOP": {GAS: (0, 0), STACK: (0, 0), ADDRESS: 0x00}, |
||||
"ADD": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x01}, |
||||
"MUL": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x02}, |
||||
"SUB": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x03}, |
||||
"DIV": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x04}, |
||||
"SDIV": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x05}, |
||||
"MOD": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x06}, |
||||
"SMOD": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x07}, |
||||
"ADDMOD": {GAS: (8, 8), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x08}, |
||||
"MULMOD": {GAS: (8, 8), STACK: T_OPERATOR_TUPLE, ADDRESS: 0x09}, |
||||
"EXP": { |
||||
GAS: (10, 340), |
||||
STACK: BIN_OPERATOR_TUPLE, |
||||
ADDRESS: 0x0A, |
||||
}, # exponent max 2^32 |
||||
"SIGNEXTEND": {GAS: (5, 5), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x0B}, |
||||
"LT": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x10}, |
||||
"GT": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x11}, |
||||
"SLT": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x12}, |
||||
"SGT": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x13}, |
||||
"EQ": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x14}, |
||||
"ISZERO": {GAS: (3, 3), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x15}, |
||||
"AND": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x16}, |
||||
"OR": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x17}, |
||||
"XOR": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x18}, |
||||
"NOT": {GAS: (3, 3), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x19}, |
||||
"BYTE": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x1A}, |
||||
"SHL": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x1B}, |
||||
"SHR": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x1C}, |
||||
"SAR": {GAS: (3, 3), STACK: BIN_OPERATOR_TUPLE, ADDRESS: 0x1D}, |
||||
"SHA3": { |
||||
GAS: ( |
||||
30, |
||||
30 + 6 * 8, |
||||
), # max can be larger, but usually storage location with 8 words |
||||
STACK: BIN_OPERATOR_TUPLE, |
||||
ADDRESS: 0x20, |
||||
}, |
||||
"ADDRESS": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x30}, |
||||
"BALANCE": {GAS: (700, 700), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x31}, |
||||
"ORIGIN": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x32}, |
||||
"CALLER": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x33}, |
||||
"CALLVALUE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x34}, |
||||
"CALLDATALOAD": {GAS: (3, 3), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x35}, |
||||
"CALLDATASIZE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x36}, |
||||
"CALLDATACOPY": { |
||||
GAS: (2, 2 + 3 * 768), # https://ethereum.stackexchange.com/a/47556 |
||||
STACK: (3, 0), |
||||
ADDRESS: 0x37, |
||||
}, |
||||
"CODESIZE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x38}, |
||||
"CODECOPY": { |
||||
GAS: (2, 2 + 3 * 768), # https://ethereum.stackexchange.com/a/47556, |
||||
STACK: (3, 0), |
||||
ADDRESS: 0x39, |
||||
}, |
||||
"GASPRICE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x3A}, |
||||
"EXTCODESIZE": {GAS: (700, 700), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x3B}, |
||||
"EXTCODECOPY": { |
||||
GAS: (700, 700 + 3 * 768), # https://ethereum.stackexchange.com/a/47556 |
||||
STACK: (4, 0), |
||||
ADDRESS: 0x3C, |
||||
}, |
||||
"EXTCODEHASH": {GAS: (700, 700), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x3F}, |
||||
"RETURNDATASIZE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x3D}, |
||||
"RETURNDATACOPY": {GAS: (3, 3), STACK: (3, 0), ADDRESS: 0x3E}, |
||||
"BLOCKHASH": {GAS: (20, 20), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x40}, |
||||
"COINBASE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x41}, |
||||
"TIMESTAMP": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x42}, |
||||
"NUMBER": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x43}, |
||||
"DIFFICULTY": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x44}, |
||||
"GASLIMIT": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x45}, |
||||
"CHAINID": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x46}, |
||||
"SELFBALANCE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x47}, |
||||
"BASEFEE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x48}, |
||||
"POP": {GAS: (2, 2), STACK: (1, 0), ADDRESS: 0x50}, |
||||
# assume 1KB memory r/w cost as upper bound |
||||
"MLOAD": {GAS: (3, 96), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x51}, |
||||
"MSTORE": {GAS: (3, 98), STACK: (2, 0), ADDRESS: 0x52}, |
||||
"MSTORE8": {GAS: (3, 98), STACK: (2, 0), ADDRESS: 0x53}, |
||||
# assume 64 byte r/w cost as upper bound |
||||
"SLOAD": {GAS: (800, 800), STACK: UN_OPERATOR_TUPLE, ADDRESS: 0x54}, |
||||
"SSTORE": {GAS: (5000, 25000), STACK: (1, 0), ADDRESS: 0x55}, |
||||
"JUMP": {GAS: (8, 8), STACK: (1, 0), ADDRESS: 0x56}, |
||||
"JUMPI": {GAS: (10, 10), STACK: (2, 0), ADDRESS: 0x57}, |
||||
"PC": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x58}, |
||||
"MSIZE": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x59}, |
||||
"GAS": {GAS: (2, 2), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x5A}, |
||||
"JUMPDEST": {GAS: (1, 1), STACK: (0, 0), ADDRESS: 0x5B}, |
||||
"BEGINSUB": {GAS: (2, 2), STACK: (0, 0), ADDRESS: 0x5C}, |
||||
"RETURNSUB": {GAS: (5, 5), STACK: (0, 0), ADDRESS: 0x5D}, |
||||
"JUMPSUB": {GAS: (10, 10), STACK: (1, 0), ADDRESS: 0x5E}, |
||||
# apparently Solidity only allows byte32 as input to the log |
||||
# function. Virtually it could be as large as the block gas limit |
||||
# allows, but let's stick to the reasonable standard here. |
||||
# https://ethereum.stackexchange.com/a/1691 |
||||
"LOG0": {GAS: (375, 375 + 8 * 32), STACK: (2, 0), ADDRESS: 0xA0}, |
||||
"LOG1": {GAS: (2 * 375, 2 * 375 + 8 * 32), STACK: (3, 0), ADDRESS: 0xA1}, |
||||
"LOG2": {GAS: (3 * 375, 3 * 375 + 8 * 32), STACK: (4, 0), ADDRESS: 0xA2}, |
||||
"LOG3": {GAS: (4 * 375, 4 * 375 + 8 * 32), STACK: (5, 0), ADDRESS: 0xA3}, |
||||
"LOG4": {GAS: (5 * 375, 5 * 375 + 8 * 32), STACK: (6, 0), ADDRESS: 0xA4}, |
||||
"CREATE": {GAS: (32000, 32000), STACK: T_OPERATOR_TUPLE, ADDRESS: 0xF0}, |
||||
"CREATE2": { |
||||
GAS: (32000, 32000), # TODO: Make the gas values dynamic |
||||
STACK: (4, 1), |
||||
ADDRESS: 0xF5, |
||||
}, |
||||
"CALL": {GAS: (700, 700 + 9000 + 25000), STACK: (7, 1), ADDRESS: 0xF1}, |
||||
"CALLCODE": {GAS: (700, 700 + 9000 + 25000), STACK: (7, 1), ADDRESS: 0xF2}, |
||||
"RETURN": {GAS: (0, 0), STACK: (2, 0), ADDRESS: 0xF3}, |
||||
"DELEGATECALL": {GAS: (700, 700 + 9000 + 25000), STACK: (6, 1), ADDRESS: 0xF4}, |
||||
"STATICCALL": {GAS: (700, 700 + 9000 + 25000), STACK: (6, 1), ADDRESS: 0xFA}, |
||||
"REVERT": {GAS: (0, 0), STACK: (2, 0), ADDRESS: 0xFD}, |
||||
"SELFDESTRUCT": {GAS: (5000, 30000), STACK: (1, 0), ADDRESS: 0xFF}, |
||||
"INVALID": {GAS: (0, 0), STACK: (0, 0), ADDRESS: 0xFE}, |
||||
} |
||||
|
||||
for i in range(1, 33): |
||||
opcodes[0x5F + i] = ("PUSH" + str(i), 0, 1, 3) |
||||
OPCODES[f"PUSH{i}"] = {GAS: (3, 3), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x5F + i} |
||||
|
||||
for i in range(1, 17): |
||||
opcodes[0x7F + i] = ("DUP" + str(i), i, i + 1, 3) |
||||
opcodes[0x8F + i] = ("SWAP" + str(i), i + 1, i + 1, 3) |
||||
OPCODES[f"DUP{i}"] = {GAS: (3, 3), STACK: (0, 0), ADDRESS: 0x7F + i} |
||||
OPCODES[f"SWAP{i}"] = {GAS: (3, 3), STACK: Z_OPERATOR_TUPLE, ADDRESS: 0x8F + i} |
||||
|
||||
ADDRESS_OPCODE_MAPPING = {} |
||||
|
||||
reverse_opcodes = {} |
||||
for o in opcodes: |
||||
vars()[opcodes[o][0]] = opcodes[o] |
||||
reverse_opcodes[opcodes[o][0]] = o |
||||
for opcode, opcode_data in OPCODES.items(): |
||||
ADDRESS_OPCODE_MAPPING[opcode_data[ADDRESS]] = opcode |
||||
|
Loading…
Reference in new issue