mirror of https://github.com/ConsenSys/mythril
commit
2f2375eb87
@ -1,6 +1,6 @@ |
||||
# We use RsT document formatting in docstring. For example :param to mark parameters. |
||||
# See PEP 287 |
||||
__docformat__ = 'restructuredtext' |
||||
__docformat__ = "restructuredtext" |
||||
|
||||
# Accept mythril.VERSION to get mythril's current version number |
||||
from .version import VERSION # NOQA |
||||
|
@ -1,125 +1,82 @@ |
||||
from z3 import * |
||||
from mythril.analysis.ops import * |
||||
from mythril.analysis import solver |
||||
from mythril.analysis.report import Issue |
||||
from mythril.analysis.swc_data import UNPROTECTED_ETHER_WITHDRAWAL |
||||
from mythril.exceptions import UnsatError |
||||
import re |
||||
import logging |
||||
|
||||
|
||||
''' |
||||
""" |
||||
MODULE DESCRIPTION: |
||||
|
||||
Check for CALLs that send >0 Ether to either the transaction sender, or to an address provided as a function argument. |
||||
If msg.sender is checked against a value in storage, check whether that storage index is tainted (i.e. there's an unconstrained write |
||||
to that index). |
||||
''' |
||||
""" |
||||
|
||||
|
||||
def execute(statespace): |
||||
def execute(state_space): |
||||
|
||||
logging.debug("Executing module: ETHER_SEND") |
||||
|
||||
issues = [] |
||||
|
||||
for call in statespace.calls: |
||||
for k in state_space.nodes: |
||||
node = state_space.nodes[k] |
||||
|
||||
state = call.state |
||||
address = state.get_current_instruction()['address'] |
||||
for state in node.states: |
||||
issues += _analyze_state(state, node) |
||||
|
||||
if "callvalue" in str(call.value): |
||||
logging.debug("[ETHER_SEND] Skipping refund function") |
||||
continue |
||||
|
||||
# We're only interested in calls that send Ether |
||||
|
||||
if call.value.type == VarType.CONCRETE and call.value.val == 0: |
||||
continue |
||||
|
||||
interesting = False |
||||
|
||||
description = "In the function `" + call.node.function_name + "` " |
||||
|
||||
if re.search(r'caller', str(call.to)): |
||||
description += "a non-zero amount of Ether is sent to msg.sender.\n" |
||||
interesting = True |
||||
|
||||
elif re.search(r'calldata', str(call.to)): |
||||
description += "a non-zero amount of Ether is sent to an address taken from function arguments.\n" |
||||
interesting = True |
||||
|
||||
else: |
||||
m = re.search(r'storage_([a-z0-9_&^]+)', str(call.to)) |
||||
|
||||
if m: |
||||
idx = m.group(1) |
||||
|
||||
description += "a non-zero amount of Ether is sent to an address taken from storage slot " + str(idx) + ".\n" |
||||
|
||||
func = statespace.find_storage_write(state.environment.active_account.address, idx) |
||||
|
||||
if func: |
||||
description += "There is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`.\n" |
||||
interesting = True |
||||
else: |
||||
logging.debug("[ETHER_SEND] No storage writes to index " + str(idx)) |
||||
|
||||
if interesting: |
||||
|
||||
node = call.node |
||||
|
||||
can_solve = True |
||||
constrained = False |
||||
|
||||
index = 0 |
||||
|
||||
while can_solve and index < len(node.constraints): |
||||
|
||||
constraint = node.constraints[index] |
||||
index += 1 |
||||
logging.debug("[ETHER_SEND] Constraint: " + str(constraint)) |
||||
|
||||
m = re.search(r'storage_([a-z0-9_&^]+)', str(constraint)) |
||||
|
||||
if m: |
||||
|
||||
constrained = True |
||||
idx = m.group(1) |
||||
|
||||
func = statespace.find_storage_write(state.environment.active_account.address, idx) |
||||
|
||||
if func: |
||||
description += "\nThere is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`." |
||||
else: |
||||
logging.debug("[ETHER_SEND] No storage writes to index " + str(idx)) |
||||
can_solve = False |
||||
break |
||||
|
||||
# CALLER may also be constrained to hardcoded address. I.e. 'caller' and some integer |
||||
|
||||
elif re.search(r"caller", str(constraint)) and re.search(r'[0-9]{20}', str(constraint)): |
||||
constrained = True |
||||
can_solve = False |
||||
break |
||||
|
||||
if not constrained: |
||||
description += "It seems that this function can be called without restrictions." |
||||
|
||||
if can_solve: |
||||
|
||||
try: |
||||
model = solver.get_model(node.constraints) |
||||
|
||||
for d in model.decls(): |
||||
logging.debug("[ETHER_SEND] main model: %s = 0x%x" % (d.name(), model[d].as_long())) |
||||
|
||||
debug = "SOLVER OUTPUT:\n" + solver.pretty_print_model(model) |
||||
return issues |
||||
|
||||
issue = Issue(call.node.contract_name, call.node.function_name, address, "Ether send", "Warning", |
||||
description, debug) |
||||
issues.append(issue) |
||||
|
||||
except UnsatError: |
||||
logging.debug("[ETHER_SEND] no model found") |
||||
def _analyze_state(state, node): |
||||
issues = [] |
||||
instruction = state.get_current_instruction() |
||||
|
||||
if instruction["opcode"] != "CALL": |
||||
return [] |
||||
|
||||
call_value = state.mstate.stack[-3] |
||||
target = state.mstate.stack[-2] |
||||
|
||||
not_creator_constraints = [] |
||||
if len(state.world_state.transaction_sequence) > 1: |
||||
creator = state.world_state.transaction_sequence[0].caller |
||||
for transaction in state.world_state.transaction_sequence[1:]: |
||||
not_creator_constraints.append( |
||||
Not(Extract(159, 0, transaction.caller) == Extract(159, 0, creator)) |
||||
) |
||||
not_creator_constraints.append( |
||||
Not(Extract(159, 0, transaction.caller) == 0) |
||||
) |
||||
|
||||
try: |
||||
model = solver.get_model( |
||||
node.constraints + not_creator_constraints + [call_value > 0] |
||||
) |
||||
|
||||
debug = "Transaction Sequence: " + str( |
||||
solver.get_transaction_sequence( |
||||
state, node.constraints + not_creator_constraints + [call_value > 0] |
||||
) |
||||
) |
||||
|
||||
issue = Issue( |
||||
contract=node.contract_name, |
||||
function_name=node.function_name, |
||||
address=instruction["address"], |
||||
swc_id=UNPROTECTED_ETHER_WITHDRAWAL, |
||||
title="Ether send", |
||||
_type="Warning", |
||||
bytecode=state.environment.code.bytecode, |
||||
description="It seems that an attacker is able to execute an call instruction," |
||||
" this can mean that the attacker is able to extract funds " |
||||
"out of the contract.".format(target), |
||||
debug=debug, |
||||
) |
||||
issues.append(issue) |
||||
except UnsatError: |
||||
logging.debug("[UNCHECKED_SUICIDE] no model found") |
||||
|
||||
return issues |
||||
|
@ -0,0 +1,27 @@ |
||||
DEFAULT_FUNCTION_VISIBILITY = "100" |
||||
INTEGER_OVERFLOW_AND_UNDERFLOW = "101" |
||||
OUTDATED_COMPILER_VERSION = "102" |
||||
FLOATING_PRAGMA = "103" |
||||
UNCHECKED_RET_VAL = "104" |
||||
UNPROTECTED_ETHER_WITHDRAWAL = "105" |
||||
UNPROTECTED_SELFDESTRUCT = "106" |
||||
REENTRANCY = "107" |
||||
DEFAULT_STATE_VARIABLE_VISIBILITY = "108" |
||||
UNINITIALIZED_STORAGE_POINTER = "109" |
||||
ASSERT_VIOLATION = "110" |
||||
DEPRICATED_FUNCTIONS_USAGE = "111" |
||||
DELEGATECALL_TO_UNTRUSTED_CONTRACT = "112" |
||||
MULTIPLE_SENDS = "113" |
||||
TX_ORDER_DEPENDENCE = "114" |
||||
TX_ORIGIN_USAGE = "115" |
||||
TIMESTAMP_DEPENDENCE = "116" |
||||
# TODO: SWC ID 116 is missing, Add it if it's added to the https://github.com/SmartContractSecurity/SWC-registry |
||||
INCORRECT_CONSTRUCTOR_NAME = "118" |
||||
SHADOWING_STATE_VARIABLES = "119" |
||||
WEAK_RANDOMNESS = "120" |
||||
SIGNATURE_REPLAY = "121" |
||||
IMPROPER_VERIFICATION_BASED_ON_MSG_SENDER = "122" |
||||
|
||||
PREDICTABLE_VARS_DEPENDENCE = ( |
||||
"N/A" |
||||
) # TODO: Add the swc id when this is added to the SWC Registry |
@ -0,0 +1,107 @@ |
||||
import re |
||||
from collections import Generator |
||||
|
||||
from ethereum.opcodes import opcodes |
||||
|
||||
regex_PUSH = re.compile("^PUSH(\d*)$") |
||||
|
||||
# Additional mnemonic to catch failed assertions |
||||
opcodes[254] = ["ASSERT_FAIL", 0, 0, 0] |
||||
|
||||
|
||||
class EvmInstruction: |
||||
""" Model to hold the information of the disassembly """ |
||||
|
||||
def __init__(self, address, op_code, argument=None): |
||||
self.address = address |
||||
self.op_code = op_code |
||||
self.argument = argument |
||||
|
||||
def to_dict(self) -> dict: |
||||
result = {"address": self.address, "opcode": self.op_code} |
||||
if self.argument: |
||||
result["argument"] = self.argument |
||||
return result |
||||
|
||||
|
||||
def instruction_list_to_easm(instruction_list: list) -> str: |
||||
result = "" |
||||
|
||||
for instruction in instruction_list: |
||||
result += "{} {}".format(instruction["address"], instruction["opcode"]) |
||||
if "argument" in instruction: |
||||
result += " " + instruction["argument"] |
||||
result += "\n" |
||||
|
||||
return result |
||||
|
||||
|
||||
def get_opcode_from_name(operation_name: str) -> int: |
||||
for op_code, value in opcodes.items(): |
||||
if operation_name == value[0]: |
||||
return op_code |
||||
raise RuntimeError("Unknown opcode") |
||||
|
||||
|
||||
def find_op_code_sequence(pattern: list, instruction_list: list) -> Generator: |
||||
""" |
||||
Returns all indices in instruction_list that point to instruction sequences following a pattern |
||||
:param pattern: The pattern to look for. |
||||
Example: [["PUSH1", "PUSH2"], ["EQ"]] where ["PUSH1", "EQ"] satisfies the pattern |
||||
:param instruction_list: List of instructions to look in |
||||
:return: Indices to the instruction sequences |
||||
""" |
||||
for i in range(0, len(instruction_list) - len(pattern) + 1): |
||||
if is_sequence_match(pattern, instruction_list, i): |
||||
yield i |
||||
|
||||
|
||||
def is_sequence_match(pattern: list, instruction_list: list, index: int) -> bool: |
||||
""" |
||||
Checks if the instructions starting at index follow a pattern |
||||
:param pattern: List of lists describing a pattern. |
||||
Example: [["PUSH1", "PUSH2"], ["EQ"]] where ["PUSH1", "EQ"] satisfies the pattern |
||||
:param instruction_list: List of instructions |
||||
:param index: Index to check for |
||||
:return: Pattern matched |
||||
""" |
||||
for index, pattern_slot in enumerate(pattern, start=index): |
||||
try: |
||||
if not instruction_list[index]["opcode"] in pattern_slot: |
||||
return False |
||||
except IndexError: |
||||
return False |
||||
return True |
||||
|
||||
|
||||
def disassemble(bytecode: str) -> list: |
||||
"""Disassembles evm bytecode and returns a list of instructions""" |
||||
instruction_list = [] |
||||
address = 0 |
||||
length = len(bytecode) |
||||
if "bzzr" in str(bytecode[-43:]): |
||||
# ignore swarm hash |
||||
length -= 43 |
||||
|
||||
while address < length: |
||||
try: |
||||
op_code = opcodes[bytecode[address]] |
||||
except KeyError: |
||||
instruction_list.append(EvmInstruction(address, "INVALID")) |
||||
address += 1 |
||||
continue |
||||
|
||||
op_code_name = op_code[0] |
||||
current_instruction = EvmInstruction(address, op_code_name) |
||||
|
||||
match = re.search(regex_PUSH, op_code_name) |
||||
if match: |
||||
argument_bytes = bytecode[address + 1 : address + 1 + int(match.group(1))] |
||||
current_instruction.argument = "0x" + argument_bytes.hex() |
||||
address += int(match.group(1)) |
||||
|
||||
instruction_list.append(current_instruction) |
||||
address += 1 |
||||
|
||||
# We use a to_dict() here for compatibility reasons |
||||
return [element.to_dict() for element in instruction_list] |
@ -1,54 +1,96 @@ |
||||
from mythril.ether import asm, util |
||||
from mythril.ether import util |
||||
from mythril.disassembler import asm |
||||
from mythril.support.signatures import SignatureDb |
||||
import logging |
||||
|
||||
|
||||
class Disassembly(object): |
||||
""" |
||||
Disassembly class |
||||
|
||||
def __init__(self, code, enable_online_lookup=True): |
||||
Stores bytecode, and its disassembly. |
||||
Additionally it will gather the following information on the existing functions in the disassembled code: |
||||
- function hashes |
||||
- function name to entry point mapping |
||||
- function entry point to function name mapping |
||||
""" |
||||
|
||||
def __init__(self, code: str, enable_online_lookup: bool = False): |
||||
self.bytecode = code |
||||
self.instruction_list = asm.disassemble(util.safe_decode(code)) |
||||
|
||||
self.func_hashes = [] |
||||
self.func_to_addr = {} |
||||
self.addr_to_func = {} |
||||
self.bytecode = code |
||||
self.function_name_to_address = {} |
||||
self.address_to_function_name = {} |
||||
|
||||
signatures = SignatureDb(enable_online_lookup=enable_online_lookup) # control if you want to have online sighash lookups |
||||
signatures = SignatureDb( |
||||
enable_online_lookup=enable_online_lookup |
||||
) # control if you want to have online signature hash lookups |
||||
try: |
||||
signatures.open() # open from default locations |
||||
except FileNotFoundError: |
||||
logging.info("Missing function signature file. Resolving of function names from signature file disabled.") |
||||
|
||||
# Parse jump table & resolve function names |
||||
|
||||
jmptable_indices = asm.find_opcode_sequence(["PUSH4", "EQ"], self.instruction_list) |
||||
|
||||
for i in jmptable_indices: |
||||
func_hash = self.instruction_list[i]['argument'] |
||||
self.func_hashes.append(func_hash) |
||||
try: |
||||
# tries local cache, file and optional online lookup |
||||
# may return more than one function signature. since we cannot probe for the correct one we'll use the first |
||||
func_names = signatures.get(func_hash) |
||||
if len(func_names) > 1: |
||||
# ambigious result |
||||
func_name = "**ambiguous** %s" % func_names[0] # return first hit but note that result was ambiguous |
||||
else: |
||||
# only one item |
||||
func_name = func_names[0] |
||||
except KeyError: |
||||
func_name = "_function_" + func_hash |
||||
|
||||
try: |
||||
offset = self.instruction_list[i + 2]['argument'] |
||||
jump_target = int(offset, 16) |
||||
|
||||
self.func_to_addr[func_name] = jump_target |
||||
self.addr_to_func[jump_target] = func_name |
||||
except: |
||||
continue |
||||
logging.info( |
||||
"Missing function signature file. Resolving of function names from signature file disabled." |
||||
) |
||||
|
||||
# Need to take from PUSH1 to PUSH4 because solc seems to remove excess 0s at the beginning for optimizing |
||||
jump_table_indices = asm.find_op_code_sequence( |
||||
[("PUSH1", "PUSH2", "PUSH3", "PUSH4"), ("EQ",)], self.instruction_list |
||||
) |
||||
|
||||
for index in jump_table_indices: |
||||
function_hash, jump_target, function_name = get_function_info( |
||||
index, self.instruction_list, signatures |
||||
) |
||||
self.func_hashes.append(function_hash) |
||||
|
||||
if jump_target is not None and function_name is not None: |
||||
self.function_name_to_address[function_name] = jump_target |
||||
self.address_to_function_name[jump_target] = function_name |
||||
|
||||
signatures.write() # store resolved signatures (potentially resolved online) |
||||
|
||||
def get_easm(self): |
||||
# todo: tintinweb - print funcsig resolved data from self.addr_to_func? |
||||
return asm.instruction_list_to_easm(self.instruction_list) |
||||
|
||||
|
||||
def get_function_info( |
||||
index: int, instruction_list: list, signature_database: SignatureDb |
||||
) -> (str, int, str): |
||||
""" |
||||
Finds the function information for a call table entry |
||||
Solidity uses the first 4 bytes of the calldata to indicate which function the message call should execute |
||||
The generated code that directs execution to the correct function looks like this: |
||||
- PUSH function_hash |
||||
- EQ |
||||
- PUSH entry_point |
||||
- JUMPI |
||||
|
||||
This function takes an index that points to the first instruction, and from that finds out the function hash, |
||||
function entry and the function name. |
||||
|
||||
:param index: Start of the entry pattern |
||||
:param instruction_list: Instruction list for the contract that is being analyzed |
||||
:param signature_database: Database used to map function hashes to their respective function names |
||||
:return: function hash, function entry point, function name |
||||
""" |
||||
|
||||
# Append with missing 0s at the beginning |
||||
function_hash = "0x" + instruction_list[index]["argument"][2:].rjust(8, "0") |
||||
|
||||
function_names = signature_database.get(function_hash) |
||||
if len(function_names) > 1: |
||||
# In this case there was an ambiguous result |
||||
function_name = "**ambiguous** {}".format(function_names[0]) |
||||
elif len(function_names) == 1: |
||||
function_name = function_names[0] |
||||
else: |
||||
function_name = "_function_" + function_hash |
||||
|
||||
try: |
||||
offset = instruction_list[index + 2]["argument"] |
||||
entry_point = int(offset, 16) |
||||
except (KeyError, IndexError): |
||||
return function_hash, None, None |
||||
|
||||
return function_hash, entry_point, function_name |
||||
|
@ -1,156 +0,0 @@ |
||||
import sys |
||||
import re |
||||
from ethereum.opcodes import opcodes |
||||
from mythril.ether import util |
||||
|
||||
|
||||
regex_PUSH = re.compile('^PUSH(\d*)$') |
||||
|
||||
# Additional mnemonic to catch failed assertions |
||||
|
||||
opcodes[254] = ['ASSERT_FAIL', 0, 0, 0] |
||||
|
||||
|
||||
def instruction_list_to_easm(instruction_list): |
||||
easm = "" |
||||
|
||||
for instruction in instruction_list: |
||||
|
||||
easm += str(instruction['address']) + " " + instruction['opcode'] |
||||
|
||||
if 'argument' in instruction: |
||||
easm += " " + instruction['argument'] |
||||
|
||||
easm += "\n" |
||||
|
||||
return easm |
||||
|
||||
|
||||
def easm_to_instruction_list(easm): |
||||
|
||||
regex_CODELINE = re.compile('^([A-Z0-9]+)(?:\s+([0-9a-fA-Fx]+))?$') |
||||
|
||||
instruction_list = [] |
||||
|
||||
codelines = easm.split('\n') |
||||
|
||||
for line in codelines: |
||||
|
||||
m = re.search(regex_CODELINE, line) |
||||
|
||||
if not m: |
||||
# Invalid code line |
||||
continue |
||||
|
||||
instruction = {} |
||||
|
||||
instruction['opcode'] = m.group(1) |
||||
|
||||
if m.group(2): |
||||
instruction['argument'] = m.group(2)[2:] |
||||
|
||||
instruction_list.append(instruction) |
||||
|
||||
return instruction_list |
||||
|
||||
|
||||
def get_opcode_from_name(name): |
||||
|
||||
for opcode, value in opcodes.items(): |
||||
|
||||
if name == value[0]: |
||||
|
||||
return opcode |
||||
|
||||
raise RuntimeError("Unknown opcode") |
||||
|
||||
|
||||
def find_opcode_sequence(pattern, instruction_list): |
||||
match_indexes = [] |
||||
|
||||
pattern_length = len(pattern) |
||||
|
||||
for i in range(0, len(instruction_list) - pattern_length + 1): |
||||
|
||||
if instruction_list[i]['opcode'] == pattern[0]: |
||||
|
||||
matched = True |
||||
|
||||
for j in range(1, len(pattern)): |
||||
|
||||
if not (instruction_list[i + j]['opcode'] == pattern[j]): |
||||
matched = False |
||||
break |
||||
|
||||
if (matched): |
||||
match_indexes.append(i) |
||||
|
||||
return match_indexes |
||||
|
||||
|
||||
def disassemble(bytecode): |
||||
|
||||
instruction_list = [] |
||||
addr = 0 |
||||
|
||||
length = len(bytecode) |
||||
|
||||
if "bzzr" in str(bytecode[-43:]): |
||||
# ignore swarm hash |
||||
length -= 43 |
||||
|
||||
while addr < length: |
||||
|
||||
instruction = {} |
||||
|
||||
instruction['address'] = addr |
||||
|
||||
try: |
||||
if (sys.version_info > (3, 0)): |
||||
opcode = opcodes[bytecode[addr]] |
||||
else: |
||||
opcode = opcodes[ord(bytecode[addr])] |
||||
|
||||
except KeyError: |
||||
|
||||
# invalid opcode |
||||
instruction_list.append({'address': addr, 'opcode': "INVALID"}) |
||||
addr += 1 |
||||
continue |
||||
|
||||
instruction['opcode'] = opcode[0] |
||||
|
||||
m = re.search(regex_PUSH, opcode[0]) |
||||
|
||||
if m: |
||||
argument = bytecode[addr+1:addr+1+int(m.group(1))] |
||||
instruction['argument'] = "0x" + argument.hex() |
||||
|
||||
addr += int(m.group(1)) |
||||
|
||||
|
||||
instruction_list.append(instruction) |
||||
|
||||
addr += 1 |
||||
|
||||
return instruction_list |
||||
|
||||
|
||||
def assemble(instruction_list): |
||||
|
||||
bytecode = b"" |
||||
|
||||
for instruction in instruction_list: |
||||
|
||||
try: |
||||
opcode = get_opcode_from_name(instruction['opcode']) |
||||
except RuntimeError: |
||||
opcode = 0xbb |
||||
|
||||
bytecode += opcode.to_bytes(1, byteorder='big') |
||||
|
||||
if 'argument' in instruction: |
||||
|
||||
bytecode += util.safe_decode(instruction['argument']) |
||||
|
||||
return bytecode |
@ -0,0 +1,4 @@ |
||||
BLOCK_TAG_EARLIEST = "earliest" |
||||
BLOCK_TAG_LATEST = "latest" |
||||
BLOCK_TAG_PENDING = "pending" |
||||
BLOCK_TAGS = (BLOCK_TAG_EARLIEST, BLOCK_TAG_LATEST, BLOCK_TAG_PENDING) |
@ -0,0 +1,249 @@ |
||||
#!/usr/bin/env python |
||||
# |
||||
# "THE BEER-WARE LICENSE" (Revision 43~maze) |
||||
# |
||||
# <maze@pyth0n.org> wrote these files. As long as you retain this notice you |
||||
# can do whatever you want with this stuff. If we meet some day, and you think |
||||
# this stuff is worth it, you can buy me a beer in return. |
||||
|
||||
# https://github.com/tehmaze/lolcat |
||||
|
||||
import atexit |
||||
import math |
||||
import os |
||||
import random |
||||
import re |
||||
import sys |
||||
import time |
||||
|
||||
PY3 = sys.version_info >= (3,) |
||||
|
||||
# Reset terminal colors at exit |
||||
def reset(): |
||||
sys.stdout.write("\x1b[0m") |
||||
sys.stdout.flush() |
||||
|
||||
|
||||
atexit.register(reset) |
||||
|
||||
|
||||
STRIP_ANSI = re.compile(r"\x1b\[(\d+)(;\d+)?(;\d+)?[m|K]") |
||||
COLOR_ANSI = ( |
||||
(0x00, 0x00, 0x00), |
||||
(0xCD, 0x00, 0x00), |
||||
(0x00, 0xCD, 0x00), |
||||
(0xCD, 0xCD, 0x00), |
||||
(0x00, 0x00, 0xEE), |
||||
(0xCD, 0x00, 0xCD), |
||||
(0x00, 0xCD, 0xCD), |
||||
(0xE5, 0xE5, 0xE5), |
||||
(0x7F, 0x7F, 0x7F), |
||||
(0xFF, 0x00, 0x00), |
||||
(0x00, 0xFF, 0x00), |
||||
(0xFF, 0xFF, 0x00), |
||||
(0x5C, 0x5C, 0xFF), |
||||
(0xFF, 0x00, 0xFF), |
||||
(0x00, 0xFF, 0xFF), |
||||
(0xFF, 0xFF, 0xFF), |
||||
) |
||||
|
||||
|
||||
class LolCat(object): |
||||
def __init__(self, mode=256, output=sys.stdout): |
||||
self.mode = mode |
||||
self.output = output |
||||
|
||||
def _distance(self, rgb1, rgb2): |
||||
return sum(map(lambda c: (c[0] - c[1]) ** 2, zip(rgb1, rgb2))) |
||||
|
||||
def ansi(self, rgb): |
||||
r, g, b = rgb |
||||
|
||||
if self.mode in (8, 16): |
||||
colors = COLOR_ANSI[: self.mode] |
||||
matches = [ |
||||
(self._distance(c, map(int, rgb)), i) for i, c in enumerate(colors) |
||||
] |
||||
matches.sort() |
||||
color = matches[0][1] |
||||
|
||||
return "3%d" % (color,) |
||||
else: |
||||
gray_possible = True |
||||
sep = 2.5 |
||||
|
||||
while gray_possible: |
||||
if r < sep or g < sep or b < sep: |
||||
gray = r < sep and g < sep and b < sep |
||||
gray_possible = False |
||||
|
||||
sep += 42.5 |
||||
|
||||
if gray: |
||||
color = 232 + int(float(sum(rgb) / 33.0)) |
||||
else: |
||||
color = sum( |
||||
[16] |
||||
+ [ |
||||
int(6 * float(val) / 256) * mod |
||||
for val, mod in zip(rgb, [36, 6, 1]) |
||||
] |
||||
) |
||||
|
||||
return "38;5;%d" % (color,) |
||||
|
||||
def wrap(self, *codes): |
||||
return "\x1b[%sm" % ("".join(codes),) |
||||
|
||||
def rainbow(self, freq, i): |
||||
r = math.sin(freq * i) * 127 + 128 |
||||
g = math.sin(freq * i + 2 * math.pi / 3) * 127 + 128 |
||||
b = math.sin(freq * i + 4 * math.pi / 3) * 127 + 128 |
||||
return [r, g, b] |
||||
|
||||
def cat(self, fd, options): |
||||
if options.animate: |
||||
self.output.write("\x1b[?25l") |
||||
|
||||
for line in fd: |
||||
options.os += 1 |
||||
self.println(line, options) |
||||
|
||||
if options.animate: |
||||
self.output.write("\x1b[?25h") |
||||
|
||||
def println(self, s, options): |
||||
s = s.rstrip() |
||||
if options.force or self.output.isatty(): |
||||
s = STRIP_ANSI.sub("", s) |
||||
|
||||
if options.animate: |
||||
self.println_ani(s, options) |
||||
else: |
||||
self.println_plain(s, options) |
||||
|
||||
self.output.write("\n") |
||||
self.output.flush() |
||||
|
||||
def println_ani(self, s, options): |
||||
if not s: |
||||
return |
||||
|
||||
for i in range(1, options.duration): |
||||
self.output.write("\x1b[%dD" % (len(s),)) |
||||
self.output.flush() |
||||
options.os += options.spread |
||||
self.println_plain(s, options) |
||||
time.sleep(1.0 / options.speed) |
||||
|
||||
def println_plain(self, s, options): |
||||
for i, c in enumerate(s if PY3 else s.decode(options.charset_py2, "replace")): |
||||
rgb = self.rainbow(options.freq, options.os + i / options.spread) |
||||
self.output.write( |
||||
"".join( |
||||
[ |
||||
self.wrap(self.ansi(rgb)), |
||||
c if PY3 else c.encode(options.charset_py2, "replace"), |
||||
] |
||||
) |
||||
) |
||||
|
||||
|
||||
def detect_mode(term_hint="xterm-256color"): |
||||
""" |
||||
Poor-mans color mode detection. |
||||
""" |
||||
if "ANSICON" in os.environ: |
||||
return 16 |
||||
elif os.environ.get("ConEmuANSI", "OFF") == "ON": |
||||
return 256 |
||||
else: |
||||
term = os.environ.get("TERM", term_hint) |
||||
if term.endswith("-256color") or term in ("xterm", "screen"): |
||||
return 256 |
||||
elif term.endswith("-color") or term in ("rxvt",): |
||||
return 16 |
||||
else: |
||||
return 256 # optimistic default |
||||
|
||||
|
||||
def run(): |
||||
"""Main entry point.""" |
||||
import optparse |
||||
|
||||
parser = optparse.OptionParser(usage=r"%prog [<options>] [file ...]") |
||||
parser.add_option( |
||||
"-p", "--spread", type="float", default=3.0, help="Rainbow spread" |
||||
) |
||||
parser.add_option( |
||||
"-F", "--freq", type="float", default=0.1, help="Rainbow frequency" |
||||
) |
||||
parser.add_option("-S", "--seed", type="int", default=0, help="Rainbow seed") |
||||
parser.add_option( |
||||
"-a", |
||||
"--animate", |
||||
action="store_true", |
||||
default=False, |
||||
help="Enable psychedelics", |
||||
) |
||||
parser.add_option( |
||||
"-d", "--duration", type="int", default=12, help="Animation duration" |
||||
) |
||||
parser.add_option( |
||||
"-s", "--speed", type="float", default=20.0, help="Animation speed" |
||||
) |
||||
parser.add_option( |
||||
"-f", |
||||
"--force", |
||||
action="store_true", |
||||
default=False, |
||||
help="Force colour even when stdout is not a tty", |
||||
) |
||||
|
||||
parser.add_option( |
||||
"-3", action="store_const", dest="mode", const=8, help="Force 3 bit colour mode" |
||||
) |
||||
parser.add_option( |
||||
"-4", |
||||
action="store_const", |
||||
dest="mode", |
||||
const=16, |
||||
help="Force 4 bit colour mode", |
||||
) |
||||
parser.add_option( |
||||
"-8", |
||||
action="store_const", |
||||
dest="mode", |
||||
const=256, |
||||
help="Force 8 bit colour mode", |
||||
) |
||||
|
||||
parser.add_option( |
||||
"-c", |
||||
"--charset-py2", |
||||
default="utf-8", |
||||
help="Manually set a charset to convert from, for python 2.7", |
||||
) |
||||
|
||||
options, args = parser.parse_args() |
||||
options.os = random.randint(0, 256) if options.seed == 0 else options.seed |
||||
options.mode = options.mode or detect_mode() |
||||
|
||||
lolcat = LolCat(mode=options.mode) |
||||
|
||||
if not args: |
||||
args = ["-"] |
||||
|
||||
for filename in args: |
||||
if filename == "-": |
||||
lolcat.cat(sys.stdin, options) |
||||
else: |
||||
try: |
||||
with open(filename, "r") as handle: |
||||
lolcat.cat(handle, options) |
||||
except IOError as error: |
||||
sys.stderr.write(str(error) + "\n") |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
sys.exit(run()) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@ |
||||
from abc import ABC, abstractmethod |
||||
|
||||
|
||||
class BasicSearchStrategy(ABC): |
||||
__slots__ = "work_list", "max_depth" |
||||
|
||||
def __init__(self, work_list, max_depth): |
||||
self.work_list = work_list |
||||
self.max_depth = max_depth |
||||
|
||||
def __iter__(self): |
||||
return self |
||||
|
||||
@abstractmethod |
||||
def get_strategic_global_state(self): |
||||
raise NotImplementedError("Must be implemented by a subclass") |
||||
|
||||
def __next__(self): |
||||
try: |
||||
global_state = self.get_strategic_global_state() |
||||
if global_state.mstate.depth >= self.max_depth: |
||||
return self.__next__() |
||||
return global_state |
||||
except IndexError: |
||||
raise StopIteration |
@ -1,54 +1,75 @@ |
||||
""" |
||||
This module implements basic symbolic execution search strategies |
||||
""" |
||||
from random import randrange |
||||
from . import BasicSearchStrategy |
||||
|
||||
try: |
||||
from random import choices |
||||
except ImportError: |
||||
|
||||
class DepthFirstSearchStrategy: |
||||
# This is for supporting python versions < 3.6 |
||||
from itertools import accumulate |
||||
from random import random |
||||
from bisect import bisect |
||||
|
||||
def choices(population, weights=None): |
||||
""" |
||||
Returns a random element out of the population based on weight. |
||||
If the relative weights or cumulative weights are not specified, |
||||
the selections are made with equal probability. |
||||
""" |
||||
if weights is None: |
||||
return [population[int(random() * len(population))]] |
||||
cum_weights = accumulate(weights) |
||||
return [ |
||||
population[ |
||||
bisect(cum_weights, random() * cum_weights[-1], 0, len(population) - 1) |
||||
] |
||||
] |
||||
|
||||
|
||||
class DepthFirstSearchStrategy(BasicSearchStrategy): |
||||
""" |
||||
Implements a depth first search strategy |
||||
I.E. Follow one path to a leaf, and then continue to the next one |
||||
""" |
||||
def __init__(self, work_list, max_depth): |
||||
self.work_list = work_list |
||||
self.max_depth = max_depth |
||||
|
||||
def __iter__(self): |
||||
return self |
||||
|
||||
def __next__(self): |
||||
""" Picks the next state to execute """ |
||||
try: |
||||
# This strategies assumes that new states are appended at the end of the work_list |
||||
# By taking the last element we effectively pick the "newest" states, which amounts to dfs |
||||
global_state = self.work_list.pop() |
||||
if global_state.mstate.depth >= self.max_depth: |
||||
return self.__next__() |
||||
return global_state |
||||
except IndexError: |
||||
raise StopIteration() |
||||
def get_strategic_global_state(self): |
||||
return self.work_list.pop() |
||||
|
||||
|
||||
class BreadthFirstSearchStrategy: |
||||
class BreadthFirstSearchStrategy(BasicSearchStrategy): |
||||
""" |
||||
Implements a breadth first search strategy |
||||
I.E. Execute all states of a "level" before continuing |
||||
""" |
||||
def __init__(self, work_list, max_depth): |
||||
self.work_list = work_list |
||||
self.max_depth = max_depth |
||||
|
||||
def __iter__(self): |
||||
return self |
||||
|
||||
def __next__(self): |
||||
""" Picks the next state to execute """ |
||||
try: |
||||
# This strategies assumes that new states are appended at the end of the work_list |
||||
# By taking the first element we effectively pick the "oldest" states, which amounts to bfs |
||||
global_state = self.work_list.pop(0) |
||||
if global_state.mstate.depth >= self.max_depth: |
||||
return self.__next__() |
||||
return global_state |
||||
except IndexError: |
||||
raise StopIteration() |
||||
|
||||
def get_strategic_global_state(self): |
||||
return self.work_list.pop(0) |
||||
|
||||
|
||||
class ReturnRandomNaivelyStrategy(BasicSearchStrategy): |
||||
""" |
||||
chooses a random state from the worklist with equal likelihood |
||||
""" |
||||
|
||||
def get_strategic_global_state(self): |
||||
if len(self.work_list) > 0: |
||||
return self.work_list.pop(randrange(len(self.work_list))) |
||||
else: |
||||
raise IndexError |
||||
|
||||
|
||||
class ReturnWeightedRandomStrategy(BasicSearchStrategy): |
||||
""" |
||||
chooses a random state from the worklist with likelihood based on inverse proportion to depth |
||||
""" |
||||
|
||||
def get_strategic_global_state(self): |
||||
probability_distribution = [ |
||||
1 / (global_state.mstate.depth + 1) for global_state in self.work_list |
||||
] |
||||
return self.work_list.pop( |
||||
choices(range(len(self.work_list)), probability_distribution)[0] |
||||
) |
||||
|
@ -1,2 +1,5 @@ |
||||
from mythril.laser.ethereum.transaction.transaction_models import * |
||||
from mythril.laser.ethereum.transaction.symbolic import execute_message_call, execute_contract_creation |
||||
from mythril.laser.ethereum.transaction.symbolic import ( |
||||
execute_message_call, |
||||
execute_contract_creation, |
||||
) |
||||
|
@ -1,8 +0,0 @@ |
||||
BLOCK_TAG_EARLIEST = 'earliest' |
||||
BLOCK_TAG_LATEST = 'latest' |
||||
BLOCK_TAG_PENDING = 'pending' |
||||
BLOCK_TAGS = ( |
||||
BLOCK_TAG_EARLIEST, |
||||
BLOCK_TAG_LATEST, |
||||
BLOCK_TAG_PENDING, |
||||
) |
@ -1,3 +1,3 @@ |
||||
# This file is suitable for sourcing inside POSIX shell, e.g. bash as |
||||
# well as for importing into Python |
||||
VERSION="v0.18.12" # NOQA |
||||
VERSION = "v0.19.3" # NOQA |
||||
|
Before Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,124 @@ |
||||
from mythril.disassembler.asm import * |
||||
import pytest |
||||
|
||||
valid_names = [("PUSH1", 0x60), ("STOP", 0x0), ("RETURN", 0xF3)] |
||||
|
||||
|
||||
@pytest.mark.parametrize("operation_name, hex_value", valid_names) |
||||
def test_get_opcode(operation_name: str, hex_value: int): |
||||
# Act |
||||
return_value = get_opcode_from_name(operation_name) |
||||
# Assert |
||||
assert return_value == hex_value |
||||
|
||||
|
||||
def test_get_unknown_opcode(): |
||||
operation_name = "definitely unknown" |
||||
|
||||
# Act |
||||
with pytest.raises(RuntimeError): |
||||
get_opcode_from_name(operation_name) |
||||
|
||||
|
||||
sequence_match_test_data = [ |
||||
# Normal no match |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
1, |
||||
False, |
||||
), |
||||
# Normal match |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH1"}, {"opcode": "EQ"}], |
||||
1, |
||||
True, |
||||
), |
||||
# Out of bounds pattern |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
3, |
||||
False, |
||||
), |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
2, |
||||
False, |
||||
), |
||||
# Double option match |
||||
( |
||||
(["PUSH1", "PUSH3"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH1"}, {"opcode": "EQ"}], |
||||
1, |
||||
True, |
||||
), |
||||
( |
||||
(["PUSH1", "PUSH3"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
1, |
||||
True, |
||||
), |
||||
# Double option no match |
||||
( |
||||
(["PUSH1", "PUSH3"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
0, |
||||
False, |
||||
), |
||||
] |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
"pattern, instruction_list, index, expected_result", sequence_match_test_data |
||||
) |
||||
def test_is_sequence_match(pattern, instruction_list, index, expected_result): |
||||
# Act |
||||
return_value = is_sequence_match(pattern, instruction_list, index) |
||||
# Assert |
||||
assert return_value == expected_result |
||||
|
||||
|
||||
find_sequence_match_test_data = [ |
||||
# Normal no match |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[{"opcode": "PUSH1"}, {"opcode": "PUSH3"}, {"opcode": "EQ"}], |
||||
[], |
||||
), |
||||
# Normal match |
||||
( |
||||
(["PUSH1"], ["EQ"]), |
||||
[ |
||||
{"opcode": "PUSH1"}, |
||||
{"opcode": "PUSH1"}, |
||||
{"opcode": "EQ"}, |
||||
{"opcode": "PUSH1"}, |
||||
{"opcode": "EQ"}, |
||||
], |
||||
[1, 3], |
||||
), |
||||
] |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
"pattern, instruction_list, expected_result", find_sequence_match_test_data |
||||
) |
||||
def test_find_op_code_sequence(pattern, instruction_list, expected_result): |
||||
# Act |
||||
return_value = list(find_op_code_sequence(pattern, instruction_list)) |
||||
|
||||
# Assert |
||||
assert return_value == expected_result |
||||
|
||||
|
||||
def test_disassemble(): |
||||
# Act |
||||
instruction_list = disassemble(b"\x00\x16\x06") |
||||
|
||||
# Assert |
||||
assert instruction_list[0]["opcode"] == "STOP" |
||||
assert instruction_list[1]["opcode"] == "AND" |
||||
assert instruction_list[2]["opcode"] == "MOD" |
@ -0,0 +1,61 @@ |
||||
from mythril.disassembler.disassembly import * |
||||
|
||||
instruction_list = [ |
||||
{"opcode": "PUSH4", "argument": "0x10203040"}, |
||||
{"opcode": "EQ"}, |
||||
{"opcode": "PUSH4", "argument": "0x40302010"}, |
||||
{"opcode": "JUMPI"}, |
||||
] |
||||
|
||||
|
||||
def test_get_function_info(mocker): |
||||
# Arrange |
||||
global instruction_list |
||||
|
||||
signature_database_mock = SignatureDb() |
||||
mocker.patch.object(signature_database_mock, "get") |
||||
signature_database_mock.get.return_value = ["function_name"] |
||||
|
||||
# Act |
||||
function_hash, entry_point, function_name = get_function_info( |
||||
0, instruction_list, signature_database_mock |
||||
) |
||||
|
||||
# Assert |
||||
assert function_hash == "0x10203040" |
||||
assert entry_point == 0x40302010 |
||||
assert function_name == "function_name" |
||||
|
||||
|
||||
def test_get_function_info_multiple_names(mocker): |
||||
# Arrange |
||||
global instruction_list |
||||
|
||||
signature_database_mock = SignatureDb() |
||||
mocker.patch.object(signature_database_mock, "get") |
||||
signature_database_mock.get.return_value = ["function_name", "another_name"] |
||||
|
||||
# Act |
||||
function_hash, entry_point, function_name = get_function_info( |
||||
0, instruction_list, signature_database_mock |
||||
) |
||||
|
||||
# Assert |
||||
assert function_name == "**ambiguous** function_name" |
||||
|
||||
|
||||
def test_get_function_info_no_names(mocker): |
||||
# Arrange |
||||
global instruction_list |
||||
|
||||
signature_database_mock = SignatureDb() |
||||
mocker.patch.object(signature_database_mock, "get") |
||||
signature_database_mock.get.return_value = [] |
||||
|
||||
# Act |
||||
function_hash, entry_point, function_name = get_function_info( |
||||
0, instruction_list, signature_database_mock |
||||
) |
||||
|
||||
# Assert |
||||
assert function_name == "_function_0x10203040" |
File diff suppressed because one or more lines are too long
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_0" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_0Filler.json", |
||||
"sourceHash" : "843009e4e97d7dd905578ea884db6d80c07f57d58679ec181dc761e1e51ae035" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x6000600020600055", |
||||
"data" : "0x", |
||||
"gas" : "0x174876e800", |
||||
"gasPrice" : "0x3b9aca00", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"gas" : "0x17487699b9", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x6000600020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x6000600020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_1" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_1Filler.json", |
||||
"sourceHash" : "5f786aded76570c96466f5a4c4632a5a0b362ffc1e4124667cdb1e9328d1d81d" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x6005600420600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"gas" : "0x013850", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x6005600420600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x6005600420600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_2" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_2Filler.json", |
||||
"sourceHash" : "bb3f59dc995c834eaf315b4819900c30ba4e97ef60163aed05946c70e841691f" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x600a600a20600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"gas" : "0x013850", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x600a600a20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0x6bd2dd6bd408cbee33429358bf24fdc64612fbf8b1b4db604518f40ffd34b607" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x600a600a20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_3" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_3Filler.json", |
||||
"sourceHash" : "1f474f7dac8971615e641354d809db332975d1ea5ca589d855fb02a1da559033" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x620fffff6103e820600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x620fffff6103e820600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_4" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_4Filler.json", |
||||
"sourceHash" : "100da75ff0b63159ca86aa4ef7457a956027af5c6c1ed1f0fa894aaa63849887" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x6064640fffffffff20600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x6064640fffffffff20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_5" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_5Filler.json", |
||||
"sourceHash" : "066bcf3a8e9e7b4c15ec2240c8e1bb0d53de0230c76989e21e4b6aaac83f577d" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x640fffffffff61271020600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x640fffffffff61271020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_6" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_6Filler.json", |
||||
"sourceHash" : "c360c6583bf965674d153f11c243c1e0807e95e99bc9bcb684a7ad2c7155dd40" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0186a0", |
||||
"gasPrice" : "0x5af3107a4000", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0x0de0b6b3a7640000" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0x152d02c7e14af6800000", |
||||
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_bigOffset" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_bigOffsetFiller.json", |
||||
"sourceHash" : "1ae2cdfa2e3ab1cac89d8b3d535c3ee50601ebc6098fdbddadca74980eec6382" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x60027e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"data" : "0x", |
||||
"gas" : "0x010000000000", |
||||
"gasPrice" : "0x01", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x60027e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_bigOffset2" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_bigOffset2Filler.json", |
||||
"sourceHash" : "2bf8d14886b1001b266c29bd9f9e764f7e6965e851bfe1440e536735fca993dc" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x6002630100000020600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0100000000", |
||||
"gasPrice" : "0x01", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
||||
}, |
||||
"gas" : "0xdfe7a9b0", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x6002630100000020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0x54a8c0ab653c15bfb48b47fd011ba2b9617af01cb45cab344acd57c924d56798" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x6002630100000020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
{ |
||||
"sha3_bigSize" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_bigSizeFiller.json", |
||||
"sourceHash" : "571bfd9a15c6b0e317f96a92f745aee1d800aa4486c1a101b3e016120ffb5415" |
||||
}, |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"data" : "0x", |
||||
"gas" : "0x010000000000", |
||||
"gasPrice" : "0x01", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_memSizeNoQuadraticCost31" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_memSizeNoQuadraticCost31Filler.json", |
||||
"sourceHash" : "04553284981ef7338bdeac0e029652313a2643169833e386ca34bfa3d5e5942a" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x60016103c020600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0100000000", |
||||
"gasPrice" : "0x01", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
||||
}, |
||||
"gas" : "0xffffb155", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x60016103c020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x60016103c020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
{ |
||||
"sha3_memSizeQuadraticCost32" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
||||
"lllcversion" : "Version: 0.4.18-develop.2017.9.25+commit.a72237f2.Linux.g++", |
||||
"source" : "src/VMTestsFiller/vmSha3Test/sha3_memSizeQuadraticCost32Filler.json", |
||||
"sourceHash" : "70f68e0328222cc2c995bf932f2f8f65f5d4c7e9f040a51bbf4dae3cad9110cf" |
||||
}, |
||||
"callcreates" : [ |
||||
], |
||||
"env" : { |
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
||||
"currentDifficulty" : "0x0100", |
||||
"currentGasLimit" : "0x0f4240", |
||||
"currentNumber" : "0x00", |
||||
"currentTimestamp" : "0x01" |
||||
}, |
||||
"exec" : { |
||||
"address" : "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", |
||||
"caller" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"code" : "0x60016103e020600055", |
||||
"data" : "0x", |
||||
"gas" : "0x0100000000", |
||||
"gasPrice" : "0x01", |
||||
"origin" : "0xcd1722f3947def4cf144679da39c4c32bdc35681", |
||||
"value" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
||||
}, |
||||
"gas" : "0xffffb151", |
||||
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"out" : "0x", |
||||
"post" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x60016103e020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
"0x00" : "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a" |
||||
} |
||||
} |
||||
}, |
||||
"pre" : { |
||||
"0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |
||||
"balance" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"code" : "0x60016103e020600055", |
||||
"nonce" : "0x00", |
||||
"storage" : { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue