mirror of https://github.com/ConsenSys/mythril
commit
6ce4ff490f
@ -0,0 +1,175 @@ |
||||
from ethereum import opcodes |
||||
from ethereum.utils import ceil32 |
||||
|
||||
|
||||
def calculate_native_gas(size: int, contract: str): |
||||
gas_value = None |
||||
word_num = ceil32(size) // 32 |
||||
if contract == "ecrecover": |
||||
gas_value = opcodes.GECRECOVER |
||||
elif contract == "sha256": |
||||
gas_value = opcodes.GSHA256BASE + word_num * opcodes.GSHA256WORD |
||||
elif contract == "ripemd160": |
||||
gas_value = opcodes.GRIPEMD160BASE + word_num * opcodes.GRIPEMD160WORD |
||||
elif contract == "identity": |
||||
gas_value = opcodes.GIDENTITYBASE + word_num * opcodes.GIDENTITYWORD |
||||
else: |
||||
raise ValueError("Unknown contract type {}".format(contract)) |
||||
return gas_value, gas_value |
||||
|
||||
|
||||
def calculate_sha3_gas(length: int): |
||||
gas_val = 30 + opcodes.GSHA3WORD * (ceil32(length) // 32) |
||||
return gas_val, gas_val |
||||
|
||||
|
||||
# opcode -> (min_gas, max_gas) |
||||
OPCODE_GAS = { |
||||
"STOP": (0, 0), |
||||
"ADD": (3, 3), |
||||
"MUL": (5, 5), |
||||
"SUB": (3, 3), |
||||
"DIV": (5, 5), |
||||
"SDIV": (5, 5), |
||||
"MOD": (5, 5), |
||||
"SMOD": (5, 5), |
||||
"ADDMOD": (8, 8), |
||||
"MULMOD": (8, 8), |
||||
"EXP": (10, 340), # exponent max 2^32 |
||||
"SIGNEXTEND": (5, 5), |
||||
"LT": (3, 3), |
||||
"GT": (3, 3), |
||||
"SLT": (3, 3), |
||||
"SGT": (3, 3), |
||||
"EQ": (3, 3), |
||||
"ISZERO": (3, 3), |
||||
"AND": (3, 3), |
||||
"OR": (3, 3), |
||||
"XOR": (3, 3), |
||||
"NOT": (3, 3), |
||||
"BYTE": (3, 3), |
||||
"SHA3": ( |
||||
30, |
||||
30 + 6 * 8, |
||||
), # max can be larger, but usually storage location with 8 words |
||||
"SHA3_FUNC": calculate_sha3_gas, |
||||
"ADDRESS": (2, 2), |
||||
"BALANCE": (400, 400), |
||||
"ORIGIN": (2, 2), |
||||
"CALLER": (2, 2), |
||||
"CALLVALUE": (2, 2), |
||||
"CALLDATALOAD": (3, 3), |
||||
"CALLDATASIZE": (2, 2), |
||||
"CALLDATACOPY": (2, 2 + 3 * 768), # https://ethereum.stackexchange.com/a/47556 |
||||
"CODESIZE": (2, 2), |
||||
"CODECOPY": (2, 2 + 3 * 768), # https://ethereum.stackexchange.com/a/47556, |
||||
"GASPRICE": (2, 2), |
||||
"EXTCODESIZE": (700, 700), |
||||
"EXTCODECOPY": (700, 700 + 3 * 768), # https://ethereum.stackexchange.com/a/47556 |
||||
"RETURNDATASIZE": (2, 2), |
||||
"RETURNDATACOPY": (3, 3), |
||||
"BLOCKHASH": (20, 20), |
||||
"COINBASE": (2, 2), |
||||
"TIMESTAMP": (2, 2), |
||||
"NUMBER": (2, 2), |
||||
"DIFFICULTY": (2, 2), |
||||
"GASLIMIT": (2, 2), |
||||
"POP": (2, 2), |
||||
# assume 1KB memory r/w cost as upper bound |
||||
"MLOAD": (3, 96), |
||||
"MSTORE": (3, 98), |
||||
"MSTORE8": (3, 98), |
||||
# assume 64 byte r/w cost as upper bound |
||||
"SLOAD": (400, 400), |
||||
"SSTORE": (5000, 25000), |
||||
"JUMP": (8, 8), |
||||
"JUMPI": (10, 10), |
||||
"PC": (2, 2), |
||||
"MSIZE": (2, 2), |
||||
"GAS": (2, 2), |
||||
"JUMPDEST": (1, 1), |
||||
"PUSH1": (3, 3), |
||||
"PUSH2": (3, 3), |
||||
"PUSH3": (3, 3), |
||||
"PUSH4": (3, 3), |
||||
"PUSH5": (3, 3), |
||||
"PUSH6": (3, 3), |
||||
"PUSH7": (3, 3), |
||||
"PUSH8": (3, 3), |
||||
"PUSH9": (3, 3), |
||||
"PUSH10": (3, 3), |
||||
"PUSH11": (3, 3), |
||||
"PUSH12": (3, 3), |
||||
"PUSH13": (3, 3), |
||||
"PUSH14": (3, 3), |
||||
"PUSH15": (3, 3), |
||||
"PUSH16": (3, 3), |
||||
"PUSH17": (3, 3), |
||||
"PUSH18": (3, 3), |
||||
"PUSH19": (3, 3), |
||||
"PUSH20": (3, 3), |
||||
"PUSH21": (3, 3), |
||||
"PUSH22": (3, 3), |
||||
"PUSH23": (3, 3), |
||||
"PUSH24": (3, 3), |
||||
"PUSH25": (3, 3), |
||||
"PUSH26": (3, 3), |
||||
"PUSH27": (3, 3), |
||||
"PUSH28": (3, 3), |
||||
"PUSH29": (3, 3), |
||||
"PUSH30": (3, 3), |
||||
"PUSH31": (3, 3), |
||||
"PUSH32": (3, 3), |
||||
"DUP1": (3, 3), |
||||
"DUP2": (3, 3), |
||||
"DUP3": (3, 3), |
||||
"DUP4": (3, 3), |
||||
"DUP5": (3, 3), |
||||
"DUP6": (3, 3), |
||||
"DUP7": (3, 3), |
||||
"DUP8": (3, 3), |
||||
"DUP9": (3, 3), |
||||
"DUP10": (3, 3), |
||||
"DUP11": (3, 3), |
||||
"DUP12": (3, 3), |
||||
"DUP13": (3, 3), |
||||
"DUP14": (3, 3), |
||||
"DUP15": (3, 3), |
||||
"DUP16": (3, 3), |
||||
"SWAP1": (3, 3), |
||||
"SWAP2": (3, 3), |
||||
"SWAP3": (3, 3), |
||||
"SWAP4": (3, 3), |
||||
"SWAP5": (3, 3), |
||||
"SWAP6": (3, 3), |
||||
"SWAP7": (3, 3), |
||||
"SWAP8": (3, 3), |
||||
"SWAP9": (3, 3), |
||||
"SWAP10": (3, 3), |
||||
"SWAP11": (3, 3), |
||||
"SWAP12": (3, 3), |
||||
"SWAP13": (3, 3), |
||||
"SWAP14": (3, 3), |
||||
"SWAP15": (3, 3), |
||||
"SWAP16": (3, 3), |
||||
# 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": (375, 375 + 8 * 32), |
||||
"LOG1": (2 * 375, 2 * 375 + 8 * 32), |
||||
"LOG2": (3 * 375, 3 * 375 + 8 * 32), |
||||
"LOG3": (4 * 375, 4 * 375 + 8 * 32), |
||||
"LOG4": (5 * 375, 5 * 375 + 8 * 32), |
||||
"CREATE": (32000, 32000), |
||||
"CALL": (700, 700 + 9000 + 25000), |
||||
"NATIVE_COST": calculate_native_gas, |
||||
"CALLCODE": (700, 700 + 9000 + 25000), |
||||
"RETURN": (0, 0), |
||||
"DELEGATECALL": (700, 700 + 9000 + 25000), |
||||
"STATICCALL": (700, 700 + 9000 + 25000), |
||||
"REVERT": (0, 0), |
||||
"SUICIDE": (5000, 30000), |
||||
"ASSERT_FAIL": (0, 0), |
||||
"INVALID": (0, 0), |
||||
} |
@ -1,571 +0,0 @@ |
||||
import struct |
||||
from z3 import ( |
||||
BitVec, |
||||
BitVecVal, |
||||
BitVecRef, |
||||
BitVecSort, |
||||
ExprRef, |
||||
Concat, |
||||
sat, |
||||
simplify, |
||||
Array, |
||||
ForAll, |
||||
Implies, |
||||
UGE, |
||||
UGT, |
||||
) |
||||
from z3.z3types import Z3Exception |
||||
from mythril.disassembler.disassembly import Disassembly |
||||
from mythril.laser.ethereum.cfg import Node |
||||
from copy import copy, deepcopy |
||||
from enum import Enum |
||||
from random import randint |
||||
from typing import KeysView, Dict, List, Union, Any, Sequence |
||||
from mythril.laser.ethereum.util import get_concrete_int |
||||
|
||||
from mythril.laser.ethereum.evm_exceptions import ( |
||||
StackOverflowException, |
||||
StackUnderflowException, |
||||
) |
||||
|
||||
|
||||
class CalldataType(Enum): |
||||
CONCRETE = 1 |
||||
SYMBOLIC = 2 |
||||
|
||||
|
||||
class Calldata: |
||||
""" |
||||
Calldata class representing the calldata of a transaction |
||||
""" |
||||
|
||||
def __init__(self, tx_id, starting_calldata=None): |
||||
""" |
||||
Constructor for Calldata |
||||
:param tx_id: unique value representing the transaction the calldata is for |
||||
:param starting_calldata: byte array representing the concrete calldata of a transaction |
||||
""" |
||||
self.tx_id = tx_id |
||||
if starting_calldata is not None: |
||||
self._calldata = [] |
||||
self.calldatasize = BitVecVal(len(starting_calldata), 256) |
||||
self.concrete = True |
||||
else: |
||||
self._calldata = Array( |
||||
"{}_calldata".format(self.tx_id), BitVecSort(256), BitVecSort(8) |
||||
) |
||||
self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id), 256) |
||||
self.concrete = False |
||||
|
||||
if self.concrete: |
||||
for calldata_byte in starting_calldata: |
||||
if type(calldata_byte) == int: |
||||
self._calldata.append(BitVecVal(calldata_byte, 8)) |
||||
else: |
||||
self._calldata.append(calldata_byte) |
||||
|
||||
def concretized(self, model): |
||||
result = [] |
||||
for i in range( |
||||
get_concrete_int(model.eval(self.calldatasize, model_completion=True)) |
||||
): |
||||
result.append( |
||||
get_concrete_int(model.eval(self._calldata[i], model_completion=True)) |
||||
) |
||||
|
||||
return result |
||||
|
||||
def get_word_at(self, index: int): |
||||
return self[index : index + 32] |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
if isinstance(item, slice): |
||||
start, step, stop = item.start, item.step, item.stop |
||||
try: |
||||
if start is None: |
||||
start = 0 |
||||
if step is None: |
||||
step = 1 |
||||
if stop is None: |
||||
stop = self.calldatasize |
||||
current_index = ( |
||||
start if isinstance(start, BitVecRef) else BitVecVal(start, 256) |
||||
) |
||||
dataparts = [] |
||||
while simplify(current_index != stop): |
||||
dataparts.append(self[current_index]) |
||||
current_index = simplify(current_index + step) |
||||
except Z3Exception: |
||||
raise IndexError("Invalid Calldata Slice") |
||||
|
||||
values, constraints = zip(*dataparts) |
||||
result_constraints = [] |
||||
for c in constraints: |
||||
result_constraints.extend(c) |
||||
return simplify(Concat(values)), result_constraints |
||||
|
||||
if self.concrete: |
||||
try: |
||||
return self._calldata[get_concrete_int(item)], () |
||||
except IndexError: |
||||
return BitVecVal(0, 8), () |
||||
else: |
||||
constraints = [ |
||||
Implies(self._calldata[item] != 0, UGT(self.calldatasize, item)) |
||||
] |
||||
|
||||
return self._calldata[item], constraints |
||||
|
||||
|
||||
class Storage: |
||||
""" |
||||
Storage class represents the storage of an Account |
||||
""" |
||||
|
||||
def __init__(self, concrete=False, address=None, dynamic_loader=None): |
||||
""" |
||||
Constructor for Storage |
||||
:param concrete: bool indicating whether to interpret uninitialized storage as concrete versus symbolic |
||||
""" |
||||
self._storage = {} |
||||
self.concrete = concrete |
||||
self.dynld = dynamic_loader |
||||
self.address = address |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
try: |
||||
return self._storage[item] |
||||
except KeyError: |
||||
if ( |
||||
self.address |
||||
and int(self.address[2:], 16) != 0 |
||||
and (self.dynld and self.dynld.storage_loading) |
||||
): |
||||
try: |
||||
self._storage[item] = int( |
||||
self.dynld.read_storage( |
||||
contract_address=self.address, index=int(item) |
||||
), |
||||
16, |
||||
) |
||||
return self._storage[item] |
||||
except ValueError: |
||||
pass |
||||
if self.concrete: |
||||
return 0 |
||||
self._storage[item] = BitVec("storage_" + str(item), 256) |
||||
return self._storage[item] |
||||
|
||||
def __setitem__(self, key: str, value: ExprRef) -> None: |
||||
self._storage[key] = value |
||||
|
||||
def keys(self) -> KeysView: |
||||
return self._storage.keys() |
||||
|
||||
|
||||
class Account: |
||||
""" |
||||
Account class representing ethereum accounts |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
address: str, |
||||
code=None, |
||||
contract_name="unknown", |
||||
balance=None, |
||||
concrete_storage=False, |
||||
dynamic_loader=None, |
||||
): |
||||
""" |
||||
Constructor for account |
||||
:param address: Address of the account |
||||
:param code: The contract code of the account |
||||
:param contract_name: The name associated with the account |
||||
:param balance: The balance for the account |
||||
:param concrete_storage: Interpret storage as concrete |
||||
""" |
||||
self.nonce = 0 |
||||
self.code = code or Disassembly("") |
||||
self.balance = balance if balance else BitVec("balance", 256) |
||||
self.storage = Storage( |
||||
concrete_storage, address=address, dynamic_loader=dynamic_loader |
||||
) |
||||
|
||||
# Metadata |
||||
self.address = address |
||||
self.contract_name = contract_name |
||||
|
||||
self.deleted = False |
||||
|
||||
def __str__(self) -> str: |
||||
return str(self.as_dict) |
||||
|
||||
def set_balance(self, balance: ExprRef) -> None: |
||||
self.balance = balance |
||||
|
||||
def add_balance(self, balance: ExprRef) -> None: |
||||
self.balance += balance |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return { |
||||
"nonce": self.nonce, |
||||
"code": self.code, |
||||
"balance": self.balance, |
||||
"storage": self.storage, |
||||
} |
||||
|
||||
|
||||
class Environment: |
||||
""" |
||||
The environment class represents the current execution environment for the symbolic executor |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
active_account: Account, |
||||
sender: ExprRef, |
||||
calldata: Calldata, |
||||
gasprice: ExprRef, |
||||
callvalue: ExprRef, |
||||
origin: ExprRef, |
||||
code=None, |
||||
calldata_type=CalldataType.SYMBOLIC, |
||||
): |
||||
# Metadata |
||||
|
||||
self.active_account = active_account |
||||
self.active_function_name = "" |
||||
|
||||
self.address = BitVecVal(int(active_account.address, 16), 256) |
||||
|
||||
# Ib |
||||
self.code = active_account.code if code is None else code |
||||
|
||||
self.sender = sender |
||||
self.calldata = calldata |
||||
self.calldata_type = calldata_type |
||||
self.gasprice = gasprice |
||||
self.origin = origin |
||||
self.callvalue = callvalue |
||||
|
||||
def __str__(self) -> str: |
||||
return str(self.as_dict) |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return dict( |
||||
active_account=self.active_account, |
||||
sender=self.sender, |
||||
calldata=self.calldata, |
||||
gasprice=self.gasprice, |
||||
callvalue=self.callvalue, |
||||
origin=self.origin, |
||||
calldata_type=self.calldata_type, |
||||
) |
||||
|
||||
|
||||
class Constraints(list): |
||||
""" |
||||
This class should maintain a solver and it's constraints, This class tries to make the Constraints() object |
||||
as a simple list of constraints with some background processing. |
||||
TODO: add the solver to this class after callback refactor |
||||
""" |
||||
|
||||
def __init__(self, constraint_list=None, solver=None, possibility=None): |
||||
super(Constraints, self).__init__(constraint_list or []) |
||||
self.solver = solver |
||||
self.__possibility = possibility |
||||
|
||||
def check_possibility(self): |
||||
return True |
||||
|
||||
def append(self, constraint): |
||||
super(Constraints, self).append(constraint) |
||||
|
||||
def pop(self, index=-1): |
||||
raise NotImplementedError |
||||
|
||||
def __copy__(self): |
||||
constraint_list = super(Constraints, self).copy() |
||||
return Constraints(constraint_list) |
||||
|
||||
def __deepcopy__(self, memodict=None): |
||||
return self.__copy__() |
||||
|
||||
def __add__(self, constraints): |
||||
constraints_list = super(Constraints, self).__add__(constraints) |
||||
return Constraints(constraint_list=constraints_list) |
||||
|
||||
def __iadd__(self, constraints): |
||||
super(Constraints, self).__iadd__(constraints) |
||||
return self |
||||
|
||||
|
||||
class MachineStack(list): |
||||
""" |
||||
Defines EVM stack, overrides the default list to handle overflows |
||||
""" |
||||
|
||||
STACK_LIMIT = 1024 |
||||
|
||||
def __init__(self, default_list=None): |
||||
if default_list is None: |
||||
default_list = [] |
||||
super(MachineStack, self).__init__(default_list) |
||||
|
||||
def append(self, element: BitVec) -> None: |
||||
""" |
||||
:param element: element to be appended to the list |
||||
:function: appends the element to list if the size is less than STACK_LIMIT, else throws an error |
||||
""" |
||||
if super(MachineStack, self).__len__() >= self.STACK_LIMIT: |
||||
raise StackOverflowException( |
||||
"Reached the EVM stack limit of {}, you can't append more " |
||||
"elements".format(self.STACK_LIMIT) |
||||
) |
||||
super(MachineStack, self).append(element) |
||||
|
||||
def pop(self, index=-1) -> BitVec: |
||||
""" |
||||
:param index:index to be popped, same as the list() class. |
||||
:returns popped value |
||||
:function: same as list() class but throws StackUnderflowException for popping from an empty list |
||||
""" |
||||
|
||||
try: |
||||
return super(MachineStack, self).pop(index) |
||||
except IndexError: |
||||
raise StackUnderflowException("Trying to pop from an empty stack") |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
try: |
||||
return super(MachineStack, self).__getitem__(item) |
||||
except IndexError: |
||||
raise StackUnderflowException( |
||||
"Trying to access a stack element which doesn't exist" |
||||
) |
||||
|
||||
def __add__(self, other): |
||||
""" |
||||
Implement list concatenation if needed |
||||
""" |
||||
raise NotImplementedError("Implement this if needed") |
||||
|
||||
def __iadd__(self, other): |
||||
""" |
||||
Implement list concatenation if needed |
||||
""" |
||||
raise NotImplementedError("Implement this if needed") |
||||
|
||||
|
||||
class MachineState: |
||||
""" |
||||
MachineState represents current machine state also referenced to as \mu |
||||
""" |
||||
|
||||
def __init__( |
||||
self, gas: int, pc=0, stack=None, memory=None, constraints=None, depth=0 |
||||
): |
||||
""" Constructor for machineState """ |
||||
self.pc = pc |
||||
self.stack = MachineStack(stack) |
||||
self.memory = memory or [] |
||||
self.gas = gas |
||||
self.constraints = constraints or Constraints() |
||||
self.depth = depth |
||||
|
||||
def mem_extend(self, start: int, size: int) -> None: |
||||
""" |
||||
Extends the memory of this machine state |
||||
:param start: Start of memory extension |
||||
:param size: Size of memory extension |
||||
""" |
||||
if self.memory_size > start + size: |
||||
return |
||||
m_extend = start + size - self.memory_size |
||||
self.memory.extend(bytearray(m_extend)) |
||||
|
||||
def memory_write(self, offset: int, data: List[int]) -> None: |
||||
""" Writes data to memory starting at offset """ |
||||
self.mem_extend(offset, len(data)) |
||||
self.memory[offset : offset + len(data)] = data |
||||
|
||||
def pop(self, amount=1) -> Union[BitVec, List[BitVec]]: |
||||
""" Pops amount elements from the stack""" |
||||
if amount > len(self.stack): |
||||
raise StackUnderflowException |
||||
values = self.stack[-amount:][::-1] |
||||
del self.stack[-amount:] |
||||
|
||||
return values[0] if amount == 1 else values |
||||
|
||||
def __deepcopy__(self, memodict=None): |
||||
memodict = {} if memodict is None else memodict |
||||
return MachineState( |
||||
gas=self.gas, |
||||
pc=self.pc, |
||||
stack=copy(self.stack), |
||||
memory=copy(self.memory), |
||||
constraints=copy(self.constraints), |
||||
depth=self.depth, |
||||
) |
||||
|
||||
def __str__(self): |
||||
return str(self.as_dict) |
||||
|
||||
@property |
||||
def memory_size(self) -> int: |
||||
return len(self.memory) |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return dict( |
||||
pc=self.pc, |
||||
stack=self.stack, |
||||
memory=self.memory, |
||||
memsize=self.memory_size, |
||||
gas=self.gas, |
||||
) |
||||
|
||||
|
||||
class GlobalState: |
||||
""" |
||||
GlobalState represents the current globalstate |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
world_state: "WorldState", |
||||
environment: Environment, |
||||
node: Node, |
||||
machine_state=None, |
||||
transaction_stack=None, |
||||
last_return_data=None, |
||||
): |
||||
""" Constructor for GlobalState""" |
||||
self.node = node |
||||
self.world_state = world_state |
||||
self.environment = environment |
||||
self.mstate = machine_state if machine_state else MachineState(gas=10000000) |
||||
self.transaction_stack = transaction_stack if transaction_stack else [] |
||||
self.op_code = "" |
||||
self.last_return_data = last_return_data |
||||
|
||||
def __copy__(self) -> "GlobalState": |
||||
world_state = copy(self.world_state) |
||||
environment = copy(self.environment) |
||||
mstate = deepcopy(self.mstate) |
||||
transaction_stack = copy(self.transaction_stack) |
||||
return GlobalState( |
||||
world_state, |
||||
environment, |
||||
self.node, |
||||
mstate, |
||||
transaction_stack=transaction_stack, |
||||
last_return_data=self.last_return_data, |
||||
) |
||||
|
||||
@property |
||||
def accounts(self) -> Dict: |
||||
return self.world_state.accounts |
||||
|
||||
# TODO: remove this, as two instructions are confusing |
||||
def get_current_instruction(self) -> Dict: |
||||
""" Gets the current instruction for this GlobalState""" |
||||
|
||||
instructions = self.environment.code.instruction_list |
||||
return instructions[self.mstate.pc] |
||||
|
||||
@property |
||||
def current_transaction( |
||||
self |
||||
) -> Union["MessageCallTransaction", "ContractCreationTransaction", None]: |
||||
# TODO: Remove circular to transaction package to import Transaction classes |
||||
try: |
||||
return self.transaction_stack[-1][0] |
||||
except IndexError: |
||||
return None |
||||
|
||||
@property |
||||
def instruction(self) -> Dict: |
||||
return self.get_current_instruction() |
||||
|
||||
def new_bitvec(self, name: str, size=256) -> BitVec: |
||||
transaction_id = self.current_transaction.id |
||||
return BitVec("{}_{}".format(transaction_id, name), size) |
||||
|
||||
|
||||
class WorldState: |
||||
""" |
||||
The WorldState class represents the world state as described in the yellow paper |
||||
""" |
||||
|
||||
def __init__(self, transaction_sequence=None): |
||||
""" |
||||
Constructor for the world state. Initializes the accounts record |
||||
""" |
||||
self.accounts = {} |
||||
self.node = None |
||||
self.transaction_sequence = transaction_sequence or [] |
||||
|
||||
def __getitem__(self, item: str) -> Account: |
||||
""" |
||||
Gets an account from the worldstate using item as key |
||||
:param item: Address of the account to get |
||||
:return: Account associated with the address |
||||
""" |
||||
return self.accounts[item] |
||||
|
||||
def __copy__(self) -> "WorldState": |
||||
new_world_state = WorldState(transaction_sequence=self.transaction_sequence[:]) |
||||
new_world_state.accounts = copy(self.accounts) |
||||
new_world_state.node = self.node |
||||
return new_world_state |
||||
|
||||
def create_account( |
||||
self, balance=0, address=None, concrete_storage=False, dynamic_loader=None |
||||
) -> Account: |
||||
""" |
||||
Create non-contract account |
||||
:param address: The account's address |
||||
:param balance: Initial balance for the account |
||||
:param concrete_storage: Interpret account storage as concrete |
||||
:param dynamic_loader: used for dynamically loading storage from the block chain |
||||
:return: The new account |
||||
""" |
||||
address = address if address else self._generate_new_address() |
||||
new_account = Account( |
||||
address, |
||||
balance=balance, |
||||
dynamic_loader=dynamic_loader, |
||||
concrete_storage=concrete_storage, |
||||
) |
||||
self._put_account(new_account) |
||||
return new_account |
||||
|
||||
def create_initialized_contract_account(self, contract_code, storage) -> None: |
||||
""" |
||||
Creates a new contract account, based on the contract code and storage provided |
||||
The contract code only includes the runtime contract bytecode |
||||
:param contract_code: Runtime bytecode for the contract |
||||
:param storage: Initial storage for the contract |
||||
:return: The new account |
||||
""" |
||||
# TODO: Add type hints |
||||
new_account = Account( |
||||
self._generate_new_address(), code=contract_code, balance=0 |
||||
) |
||||
new_account.storage = storage |
||||
self._put_account(new_account) |
||||
|
||||
def _generate_new_address(self) -> str: |
||||
""" Generates a new address for the global state""" |
||||
while True: |
||||
address = "0x" + "".join([str(hex(randint(0, 16)))[-1] for _ in range(20)]) |
||||
if address not in self.accounts.keys(): |
||||
return address |
||||
|
||||
def _put_account(self, account: Account) -> None: |
||||
self.accounts[account.address] = account |
@ -0,0 +1 @@ |
||||
# Hello! |
@ -0,0 +1,105 @@ |
||||
from typing import Dict, Union, Any, KeysView |
||||
|
||||
from z3 import BitVec, ExprRef |
||||
|
||||
from mythril.disassembler.disassembly import Disassembly |
||||
|
||||
|
||||
class Storage: |
||||
""" |
||||
Storage class represents the storage of an Account |
||||
""" |
||||
|
||||
def __init__(self, concrete=False, address=None, dynamic_loader=None): |
||||
""" |
||||
Constructor for Storage |
||||
:param concrete: bool indicating whether to interpret uninitialized storage as concrete versus symbolic |
||||
""" |
||||
self._storage = {} |
||||
self.concrete = concrete |
||||
self.dynld = dynamic_loader |
||||
self.address = address |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
try: |
||||
return self._storage[item] |
||||
except KeyError: |
||||
if ( |
||||
self.address |
||||
and int(self.address[2:], 16) != 0 |
||||
and (self.dynld and self.dynld.storage_loading) |
||||
): |
||||
try: |
||||
self._storage[item] = int( |
||||
self.dynld.read_storage( |
||||
contract_address=self.address, index=int(item) |
||||
), |
||||
16, |
||||
) |
||||
return self._storage[item] |
||||
except ValueError: |
||||
pass |
||||
if self.concrete: |
||||
return 0 |
||||
self._storage[item] = BitVec("storage_" + str(item), 256) |
||||
return self._storage[item] |
||||
|
||||
def __setitem__(self, key: str, value: ExprRef) -> None: |
||||
self._storage[key] = value |
||||
|
||||
def keys(self) -> KeysView: |
||||
return self._storage.keys() |
||||
|
||||
|
||||
class Account: |
||||
""" |
||||
Account class representing ethereum accounts |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
address: str, |
||||
code=None, |
||||
contract_name="unknown", |
||||
balance=None, |
||||
concrete_storage=False, |
||||
dynamic_loader=None, |
||||
): |
||||
""" |
||||
Constructor for account |
||||
:param address: Address of the account |
||||
:param code: The contract code of the account |
||||
:param contract_name: The name associated with the account |
||||
:param balance: The balance for the account |
||||
:param concrete_storage: Interpret storage as concrete |
||||
""" |
||||
self.nonce = 0 |
||||
self.code = code or Disassembly("") |
||||
self.balance = balance if balance else BitVec("balance", 256) |
||||
self.storage = Storage( |
||||
concrete_storage, address=address, dynamic_loader=dynamic_loader |
||||
) |
||||
|
||||
# Metadata |
||||
self.address = address |
||||
self.contract_name = contract_name |
||||
|
||||
self.deleted = False |
||||
|
||||
def __str__(self) -> str: |
||||
return str(self.as_dict) |
||||
|
||||
def set_balance(self, balance: ExprRef) -> None: |
||||
self.balance = balance |
||||
|
||||
def add_balance(self, balance: ExprRef) -> None: |
||||
self.balance += balance |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return { |
||||
"nonce": self.nonce, |
||||
"code": self.code, |
||||
"balance": self.balance, |
||||
"storage": self.storage, |
||||
} |
@ -0,0 +1,104 @@ |
||||
from enum import Enum |
||||
from typing import Union, Any |
||||
from z3 import ( |
||||
BitVecVal, |
||||
BitVecRef, |
||||
BitVecSort, |
||||
BitVec, |
||||
Implies, |
||||
simplify, |
||||
Concat, |
||||
UGT, |
||||
Array, |
||||
) |
||||
from z3.z3types import Z3Exception |
||||
|
||||
from mythril.laser.ethereum.util import get_concrete_int |
||||
|
||||
|
||||
class CalldataType(Enum): |
||||
CONCRETE = 1 |
||||
SYMBOLIC = 2 |
||||
|
||||
|
||||
class Calldata: |
||||
""" |
||||
Calldata class representing the calldata of a transaction |
||||
""" |
||||
|
||||
def __init__(self, tx_id, starting_calldata=None): |
||||
""" |
||||
Constructor for Calldata |
||||
:param tx_id: unique value representing the transaction the calldata is for |
||||
:param starting_calldata: byte array representing the concrete calldata of a transaction |
||||
""" |
||||
self.tx_id = tx_id |
||||
if starting_calldata is not None: |
||||
self._calldata = [] |
||||
self.calldatasize = BitVecVal(len(starting_calldata), 256) |
||||
self.concrete = True |
||||
else: |
||||
self._calldata = Array( |
||||
"{}_calldata".format(self.tx_id), BitVecSort(256), BitVecSort(8) |
||||
) |
||||
self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id), 256) |
||||
self.concrete = False |
||||
|
||||
if self.concrete: |
||||
for calldata_byte in starting_calldata: |
||||
if type(calldata_byte) == int: |
||||
self._calldata.append(BitVecVal(calldata_byte, 8)) |
||||
else: |
||||
self._calldata.append(calldata_byte) |
||||
|
||||
def concretized(self, model): |
||||
result = [] |
||||
for i in range( |
||||
get_concrete_int(model.eval(self.calldatasize, model_completion=True)) |
||||
): |
||||
result.append( |
||||
get_concrete_int(model.eval(self._calldata[i], model_completion=True)) |
||||
) |
||||
|
||||
return result |
||||
|
||||
def get_word_at(self, index: int): |
||||
return self[index : index + 32] |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
if isinstance(item, slice): |
||||
start, step, stop = item.start, item.step, item.stop |
||||
try: |
||||
if start is None: |
||||
start = 0 |
||||
if step is None: |
||||
step = 1 |
||||
if stop is None: |
||||
stop = self.calldatasize |
||||
current_index = ( |
||||
start if isinstance(start, BitVecRef) else BitVecVal(start, 256) |
||||
) |
||||
dataparts = [] |
||||
while simplify(current_index != stop): |
||||
dataparts.append(self[current_index]) |
||||
current_index = simplify(current_index + step) |
||||
except Z3Exception: |
||||
raise IndexError("Invalid Calldata Slice") |
||||
|
||||
values, constraints = zip(*dataparts) |
||||
result_constraints = [] |
||||
for c in constraints: |
||||
result_constraints.extend(c) |
||||
return simplify(Concat(values)), result_constraints |
||||
|
||||
if self.concrete: |
||||
try: |
||||
return self._calldata[get_concrete_int(item)], () |
||||
except IndexError: |
||||
return BitVecVal(0, 8), () |
||||
else: |
||||
constraints = [ |
||||
Implies(self._calldata[item] != 0, UGT(self.calldatasize, item)) |
||||
] |
||||
|
||||
return self._calldata[item], constraints |
@ -0,0 +1,35 @@ |
||||
class Constraints(list): |
||||
""" |
||||
This class should maintain a solver and it's constraints, This class tries to make the Constraints() object |
||||
as a simple list of constraints with some background processing. |
||||
TODO: add the solver to this class after callback refactor |
||||
""" |
||||
|
||||
def __init__(self, constraint_list=None, solver=None, possibility=None): |
||||
super(Constraints, self).__init__(constraint_list or []) |
||||
self.solver = solver |
||||
self.__possibility = possibility |
||||
|
||||
def check_possibility(self): |
||||
return True |
||||
|
||||
def append(self, constraint): |
||||
super(Constraints, self).append(constraint) |
||||
|
||||
def pop(self, index=-1): |
||||
raise NotImplementedError |
||||
|
||||
def __copy__(self): |
||||
constraint_list = super(Constraints, self).copy() |
||||
return Constraints(constraint_list) |
||||
|
||||
def __deepcopy__(self, memodict=None): |
||||
return self.__copy__() |
||||
|
||||
def __add__(self, constraints): |
||||
constraints_list = super(Constraints, self).__add__(constraints) |
||||
return Constraints(constraint_list=constraints_list) |
||||
|
||||
def __iadd__(self, constraints): |
||||
super(Constraints, self).__iadd__(constraints) |
||||
return self |
@ -0,0 +1,55 @@ |
||||
from typing import Dict |
||||
|
||||
from z3 import ExprRef, BitVecVal |
||||
|
||||
from mythril.laser.ethereum.state.account import Account |
||||
from mythril.laser.ethereum.state.calldata import Calldata, CalldataType |
||||
|
||||
|
||||
class Environment: |
||||
""" |
||||
The environment class represents the current execution environment for the symbolic executor |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
active_account: Account, |
||||
sender: ExprRef, |
||||
calldata: Calldata, |
||||
gasprice: ExprRef, |
||||
callvalue: ExprRef, |
||||
origin: ExprRef, |
||||
code=None, |
||||
calldata_type=CalldataType.SYMBOLIC, |
||||
): |
||||
# Metadata |
||||
|
||||
self.active_account = active_account |
||||
self.active_function_name = "" |
||||
|
||||
self.address = BitVecVal(int(active_account.address, 16), 256) |
||||
|
||||
# Ib |
||||
self.code = active_account.code if code is None else code |
||||
|
||||
self.sender = sender |
||||
self.calldata = calldata |
||||
self.calldata_type = calldata_type |
||||
self.gasprice = gasprice |
||||
self.origin = origin |
||||
self.callvalue = callvalue |
||||
|
||||
def __str__(self) -> str: |
||||
return str(self.as_dict) |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return dict( |
||||
active_account=self.active_account, |
||||
sender=self.sender, |
||||
calldata=self.calldata, |
||||
gasprice=self.gasprice, |
||||
callvalue=self.callvalue, |
||||
origin=self.origin, |
||||
calldata_type=self.calldata_type, |
||||
) |
@ -0,0 +1,77 @@ |
||||
from typing import Dict, Union |
||||
|
||||
from copy import copy, deepcopy |
||||
from z3 import BitVec |
||||
|
||||
from mythril.laser.ethereum.cfg import Node |
||||
from mythril.laser.ethereum.state.environment import Environment |
||||
from mythril.laser.ethereum.state.machine_state import MachineState |
||||
|
||||
|
||||
class GlobalState: |
||||
""" |
||||
GlobalState represents the current globalstate |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
world_state: "WorldState", |
||||
environment: Environment, |
||||
node: Node, |
||||
machine_state=None, |
||||
transaction_stack=None, |
||||
last_return_data=None, |
||||
): |
||||
""" Constructor for GlobalState""" |
||||
self.node = node |
||||
self.world_state = world_state |
||||
self.environment = environment |
||||
self.mstate = ( |
||||
machine_state if machine_state else MachineState(gas_limit=1000000000) |
||||
) |
||||
self.transaction_stack = transaction_stack if transaction_stack else [] |
||||
self.op_code = "" |
||||
self.last_return_data = last_return_data |
||||
|
||||
def __copy__(self) -> "GlobalState": |
||||
world_state = copy(self.world_state) |
||||
environment = copy(self.environment) |
||||
mstate = deepcopy(self.mstate) |
||||
transaction_stack = copy(self.transaction_stack) |
||||
return GlobalState( |
||||
world_state, |
||||
environment, |
||||
self.node, |
||||
mstate, |
||||
transaction_stack=transaction_stack, |
||||
last_return_data=self.last_return_data, |
||||
) |
||||
|
||||
@property |
||||
def accounts(self) -> Dict: |
||||
return self.world_state.accounts |
||||
|
||||
# TODO: remove this, as two instructions are confusing |
||||
def get_current_instruction(self) -> Dict: |
||||
""" Gets the current instruction for this GlobalState""" |
||||
|
||||
instructions = self.environment.code.instruction_list |
||||
return instructions[self.mstate.pc] |
||||
|
||||
@property |
||||
def current_transaction( |
||||
self |
||||
) -> Union["MessageCallTransaction", "ContractCreationTransaction", None]: |
||||
# TODO: Remove circular to transaction package to import Transaction classes |
||||
try: |
||||
return self.transaction_stack[-1][0] |
||||
except IndexError: |
||||
return None |
||||
|
||||
@property |
||||
def instruction(self) -> Dict: |
||||
return self.get_current_instruction() |
||||
|
||||
def new_bitvec(self, name: str, size=256) -> BitVec: |
||||
transaction_id = self.current_transaction.id |
||||
return BitVec("{}_{}".format(transaction_id, name), size) |
@ -0,0 +1,177 @@ |
||||
from copy import copy |
||||
from typing import Union, Any, List, Dict |
||||
|
||||
from z3 import BitVec |
||||
|
||||
from ethereum import opcodes, utils |
||||
from mythril.laser.ethereum.evm_exceptions import ( |
||||
StackOverflowException, |
||||
StackUnderflowException, |
||||
OutOfGasException, |
||||
) |
||||
from mythril.laser.ethereum.state.constraints import Constraints |
||||
|
||||
|
||||
class MachineStack(list): |
||||
""" |
||||
Defines EVM stack, overrides the default list to handle overflows |
||||
""" |
||||
|
||||
STACK_LIMIT = 1024 |
||||
|
||||
def __init__(self, default_list=None): |
||||
if default_list is None: |
||||
default_list = [] |
||||
super(MachineStack, self).__init__(default_list) |
||||
|
||||
def append(self, element: BitVec) -> None: |
||||
""" |
||||
:param element: element to be appended to the list |
||||
:function: appends the element to list if the size is less than STACK_LIMIT, else throws an error |
||||
""" |
||||
if super(MachineStack, self).__len__() >= self.STACK_LIMIT: |
||||
raise StackOverflowException( |
||||
"Reached the EVM stack limit of {}, you can't append more " |
||||
"elements".format(self.STACK_LIMIT) |
||||
) |
||||
super(MachineStack, self).append(element) |
||||
|
||||
def pop(self, index=-1) -> BitVec: |
||||
""" |
||||
:param index:index to be popped, same as the list() class. |
||||
:returns popped value |
||||
:function: same as list() class but throws StackUnderflowException for popping from an empty list |
||||
""" |
||||
|
||||
try: |
||||
return super(MachineStack, self).pop(index) |
||||
except IndexError: |
||||
raise StackUnderflowException("Trying to pop from an empty stack") |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Any: |
||||
try: |
||||
return super(MachineStack, self).__getitem__(item) |
||||
except IndexError: |
||||
raise StackUnderflowException( |
||||
"Trying to access a stack element which doesn't exist" |
||||
) |
||||
|
||||
def __add__(self, other): |
||||
""" |
||||
Implement list concatenation if needed |
||||
""" |
||||
raise NotImplementedError("Implement this if needed") |
||||
|
||||
def __iadd__(self, other): |
||||
""" |
||||
Implement list concatenation if needed |
||||
""" |
||||
raise NotImplementedError("Implement this if needed") |
||||
|
||||
|
||||
class MachineState: |
||||
""" |
||||
MachineState represents current machine state also referenced to as \mu |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
gas_limit: int, |
||||
pc=0, |
||||
stack=None, |
||||
memory=None, |
||||
constraints=None, |
||||
depth=0, |
||||
max_gas_used=0, |
||||
min_gas_used=0, |
||||
): |
||||
""" Constructor for machineState """ |
||||
self.pc = pc |
||||
self.stack = MachineStack(stack) |
||||
self.memory = memory or [] |
||||
self.gas_limit = gas_limit |
||||
self.min_gas_used = min_gas_used # lower gas usage bound |
||||
self.max_gas_used = max_gas_used # upper gas usage bound |
||||
self.constraints = constraints or Constraints() |
||||
self.depth = depth |
||||
|
||||
def calculate_extension_size(self, start: int, size: int) -> int: |
||||
if self.memory_size > start + size: |
||||
return 0 |
||||
return start + size - self.memory_size |
||||
|
||||
def calculate_memory_gas(self, start: int, size: int): |
||||
# https://github.com/ethereum/pyethereum/blob/develop/ethereum/vm.py#L148 |
||||
oldsize = self.memory_size // 32 |
||||
old_totalfee = ( |
||||
oldsize * opcodes.GMEMORY + oldsize ** 2 // opcodes.GQUADRATICMEMDENOM |
||||
) |
||||
newsize = utils.ceil32(start + size) // 32 |
||||
new_totalfee = ( |
||||
newsize * opcodes.GMEMORY + newsize ** 2 // opcodes.GQUADRATICMEMDENOM |
||||
) |
||||
return new_totalfee - old_totalfee |
||||
|
||||
def check_gas(self): |
||||
if self.min_gas_used > self.gas_limit: |
||||
raise OutOfGasException() |
||||
|
||||
def mem_extend(self, start: int, size: int) -> None: |
||||
""" |
||||
Extends the memory of this machine state |
||||
:param start: Start of memory extension |
||||
:param size: Size of memory extension |
||||
""" |
||||
m_extend = self.calculate_extension_size(start, size) |
||||
if m_extend: |
||||
extend_gas = self.calculate_memory_gas(start, size) |
||||
self.min_gas_used += extend_gas |
||||
self.max_gas_used += extend_gas |
||||
self.check_gas() |
||||
self.memory.extend(bytearray(m_extend)) |
||||
|
||||
def memory_write(self, offset: int, data: List[int]) -> None: |
||||
""" Writes data to memory starting at offset """ |
||||
self.mem_extend(offset, len(data)) |
||||
self.memory[offset : offset + len(data)] = data |
||||
|
||||
def pop(self, amount=1) -> Union[BitVec, List[BitVec]]: |
||||
""" Pops amount elements from the stack""" |
||||
if amount > len(self.stack): |
||||
raise StackUnderflowException |
||||
values = self.stack[-amount:][::-1] |
||||
del self.stack[-amount:] |
||||
|
||||
return values[0] if amount == 1 else values |
||||
|
||||
def __deepcopy__(self, memodict=None): |
||||
memodict = {} if memodict is None else memodict |
||||
return MachineState( |
||||
gas_limit=self.gas_limit, |
||||
max_gas_used=self.max_gas_used, |
||||
min_gas_used=self.min_gas_used, |
||||
pc=self.pc, |
||||
stack=copy(self.stack), |
||||
memory=copy(self.memory), |
||||
constraints=copy(self.constraints), |
||||
depth=self.depth, |
||||
) |
||||
|
||||
def __str__(self): |
||||
return str(self.as_dict) |
||||
|
||||
@property |
||||
def memory_size(self) -> int: |
||||
return len(self.memory) |
||||
|
||||
@property |
||||
def as_dict(self) -> Dict: |
||||
return dict( |
||||
pc=self.pc, |
||||
stack=self.stack, |
||||
memory=self.memory, |
||||
memsize=self.memory_size, |
||||
gas=self.gas_limit, |
||||
max_gas_used=self.max_gas_used, |
||||
min_gas_used=self.min_gas_used, |
||||
) |
@ -0,0 +1,78 @@ |
||||
from copy import copy |
||||
from random import randint |
||||
|
||||
from mythril.laser.ethereum.state.account import Account |
||||
|
||||
|
||||
class WorldState: |
||||
""" |
||||
The WorldState class represents the world state as described in the yellow paper |
||||
""" |
||||
|
||||
def __init__(self, transaction_sequence=None): |
||||
""" |
||||
Constructor for the world state. Initializes the accounts record |
||||
""" |
||||
self.accounts = {} |
||||
self.node = None |
||||
self.transaction_sequence = transaction_sequence or [] |
||||
|
||||
def __getitem__(self, item: str) -> Account: |
||||
""" |
||||
Gets an account from the worldstate using item as key |
||||
:param item: Address of the account to get |
||||
:return: Account associated with the address |
||||
""" |
||||
return self.accounts[item] |
||||
|
||||
def __copy__(self) -> "WorldState": |
||||
new_world_state = WorldState(transaction_sequence=self.transaction_sequence[:]) |
||||
new_world_state.accounts = copy(self.accounts) |
||||
new_world_state.node = self.node |
||||
return new_world_state |
||||
|
||||
def create_account( |
||||
self, balance=0, address=None, concrete_storage=False, dynamic_loader=None |
||||
) -> Account: |
||||
""" |
||||
Create non-contract account |
||||
:param address: The account's address |
||||
:param balance: Initial balance for the account |
||||
:param concrete_storage: Interpret account storage as concrete |
||||
:param dynamic_loader: used for dynamically loading storage from the block chain |
||||
:return: The new account |
||||
""" |
||||
address = address if address else self._generate_new_address() |
||||
new_account = Account( |
||||
address, |
||||
balance=balance, |
||||
dynamic_loader=dynamic_loader, |
||||
concrete_storage=concrete_storage, |
||||
) |
||||
self._put_account(new_account) |
||||
return new_account |
||||
|
||||
def create_initialized_contract_account(self, contract_code, storage) -> None: |
||||
""" |
||||
Creates a new contract account, based on the contract code and storage provided |
||||
The contract code only includes the runtime contract bytecode |
||||
:param contract_code: Runtime bytecode for the contract |
||||
:param storage: Initial storage for the contract |
||||
:return: The new account |
||||
""" |
||||
# TODO: Add type hints |
||||
new_account = Account( |
||||
self._generate_new_address(), code=contract_code, balance=0 |
||||
) |
||||
new_account.storage = storage |
||||
self._put_account(new_account) |
||||
|
||||
def _generate_new_address(self) -> str: |
||||
""" Generates a new address for the global state""" |
||||
while True: |
||||
address = "0x" + "".join([str(hex(randint(0, 16)))[-1] for _ in range(20)]) |
||||
if address not in self.accounts.keys(): |
||||
return address |
||||
|
||||
def _put_account(self, account: Account) -> None: |
||||
self.accounts[account.address] = account |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"calldatacopyUnderFlow" : { |
||||
"calldatacopyUnderFlowerror" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "testeth 1.5.0.dev2-52+commit.d419e0a2", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_3" : { |
||||
"sha3_3oog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_4" : { |
||||
"sha3_4oog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_5" : { |
||||
"sha3_5oog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_6" : { |
||||
"sha3_6oog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_bigOffset" : { |
||||
"sha3_bigOffsetoog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1,5 +1,5 @@ |
||||
{ |
||||
"sha3_bigSize" : { |
||||
"sha3_bigSizeoog" : { |
||||
"_info" : { |
||||
"comment" : "", |
||||
"filledwith" : "cpp-1.3.0+commit.6e0ce939.Linux.g++", |
@ -1 +1,126 @@ |
||||
{"error": null, "issues": [{"address": 661, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x5a6814ec", "swc-id": "107", "title": "Message call to external contract", "type": "Informational"}, {"address": 666, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x5a6814ec", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `_function_0x2776b163`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xd24b08cc", "swc-id": "107", "title": "Message call to external contract", "type": "Warning"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location", "function": "_function_0xd24b08cc", "swc-id": "114", "title": "Transaction order dependence", "type": "Warning"}, {"address": 784, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xd24b08cc", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 858, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe11f493e", "swc-id": "107", "title": "Message call to external contract", "type": "Informational"}, {"address": 869, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", "function": "_function_0xe11f493e", "swc-id": "107", "title": "State change after external call", "type": "Warning"}, {"address": 871, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe11f493e", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 912, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xe1d10f79", "swc-id": "107", "title": "Message call to external contract", "type": "Warning"}, {"address": 918, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe1d10f79", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 661, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "_function_0x5a6814ec", |
||||
"swc-id": "107", |
||||
"min_gas_used": 643, |
||||
"max_gas_used": 1254, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 666, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x5a6814ec", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1352, |
||||
"max_gas_used": 35963, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `_function_0x2776b163`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "_function_0xd24b08cc", |
||||
"swc-id": "107", |
||||
"min_gas_used": 687, |
||||
"max_gas_used": 1298, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location", |
||||
"function": "_function_0xd24b08cc", |
||||
"swc-id": "114", |
||||
"min_gas_used": 687, |
||||
"max_gas_used": 1298, |
||||
"title": "Transaction order dependence", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 784, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xd24b08cc", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1396, |
||||
"max_gas_used": 36007, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 858, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "107", |
||||
"min_gas_used": 709, |
||||
"max_gas_used": 1320, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 869, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "107", |
||||
"min_gas_used": 709, |
||||
"max_gas_used": 1320, |
||||
"title": "State change after external call", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 871, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "104", |
||||
"min_gas_used": 6432, |
||||
"max_gas_used": 61043, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 912, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "_function_0xe1d10f79", |
||||
"swc-id": "107", |
||||
"min_gas_used": 335, |
||||
"max_gas_used": 616, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 918, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xe1d10f79", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1046, |
||||
"max_gas_used": 35327, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,36 @@ |
||||
{"error": null, "issues": [{"address": 158, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The arithmetic operation can result in integer overflow.\n", "function": "_function_0x83f12fec", "swc-id": "101", "title": "Integer Overflow", "type": "Warning"}, {"address": 278, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The arithmetic operation can result in integer overflow.\n", "function": "_function_0x83f12fec", "swc-id": "101", "title": "Integer Overflow", "type": "Warning"}, {"address": 378, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The substraction can result in an integer underflow.\n", "function": "_function_0x83f12fec", "swc-id": "101", "title": "Integer Underflow", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 158, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 278, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 378, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The substraction can result in an integer underflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,30 @@ |
||||
{"error": null, "issues": [{"address": 722, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", "function": "withdrawfunds()", "swc-id": "105", "title": "Ether thief", "type": "Warning"}, {"address": 883, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This binary add operation can result in integer overflow.\n", "function": "invest()", "swc-id": "101", "title": "Integer Overflow", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 722, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", |
||||
"function": "withdrawfunds()", |
||||
"swc-id": "105", |
||||
"min_gas_used": 1138, |
||||
"max_gas_used": 1749, |
||||
"title": "Ether thief", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 883, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This binary add operation can result in integer overflow.\n", |
||||
"function": "invest()", |
||||
"swc-id": "101", |
||||
"min_gas_used": 1571, |
||||
"max_gas_used": 1856, |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,54 @@ |
||||
{"error": null, "issues": [{"address": 446, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x546455b5", "swc-id": "110", "title": "Exception state", "type": "Informational"}, {"address": 484, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x92dd38ea", "swc-id": "110", "title": "Exception state", "type": "Informational"}, {"address": 506, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xa08299f1", "swc-id": "110", "title": "Exception state", "type": "Informational"}, {"address": 531, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xb34c3610", "swc-id": "110", "title": "Exception state", "type": "Informational"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 446, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", |
||||
"function": "_function_0x546455b5", |
||||
"swc-id": "110", |
||||
"min_gas_used": 206, |
||||
"max_gas_used": 301, |
||||
"title": "Exception state", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 484, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", |
||||
"function": "_function_0x92dd38ea", |
||||
"swc-id": "110", |
||||
"min_gas_used": 256, |
||||
"max_gas_used": 351, |
||||
"title": "Exception state", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 506, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", |
||||
"function": "_function_0xa08299f1", |
||||
"swc-id": "110", |
||||
"min_gas_used": 272, |
||||
"max_gas_used": 367, |
||||
"title": "Exception state", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 531, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", |
||||
"function": "_function_0xb34c3610", |
||||
"swc-id": "110", |
||||
"min_gas_used": 268, |
||||
"max_gas_used": 363, |
||||
"title": "Exception state", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,54 @@ |
||||
{"error": null, "issues": [{"address": 626, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xeea4c864", "swc-id": "107", "title": "Message call to external contract", "type": "Warning"}, {"address": 1046, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 626, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x141f32ff", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1104, |
||||
"max_gas_used": 35856, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 857, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x9b58bc26", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1167, |
||||
"max_gas_used": 35919, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 1038, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "_function_0xeea4c864", |
||||
"swc-id": "107", |
||||
"min_gas_used": 477, |
||||
"max_gas_used": 1229, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 1046, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xeea4c864", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1192, |
||||
"max_gas_used": 35944, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,5 @@ |
||||
{"error": null, "issues": [], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,18 @@ |
||||
{"error": null, "issues": [{"address": 142, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", "function": "_function_0x8a4068dd", "swc-id": "105", "title": "Ether thief", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 142, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Users other than the contract creator can withdraw ETH from the contract account without previously having sent any ETH to it. This is likely to be vulnerability.", |
||||
"function": "_function_0x8a4068dd", |
||||
"swc-id": "105", |
||||
"min_gas_used": 186, |
||||
"max_gas_used": 467, |
||||
"title": "Ether thief", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,5 @@ |
||||
{"error": null, "issues": [], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,18 @@ |
||||
{"error": null, "issues": [{"address": 317, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The function `transferOwnership(address)` retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", "function": "transferOwnership(address)", "swc-id": "115", "title": "Use of tx.origin", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 317, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The function `transferOwnership(address)` retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", |
||||
"function": "transferOwnership(address)", |
||||
"swc-id": "115", |
||||
"min_gas_used": 626, |
||||
"max_gas_used": 1051, |
||||
"title": "Use of tx.origin", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,42 @@ |
||||
{"error":null,"issues":[{"address":567,"contract":"Unknown","debug":"<DEBUG-DATA>","description":"The subtraction can result in an integer underflow.\n","function":"sendeth(address,uint256)","swc-id":"101","title":"Integer Underflow","type":"Warning"},{"address":649,"contract":"Unknown","debug":"<DEBUG-DATA>","description":"The subtraction can result in an integer underflow.\n","function":"sendeth(address,uint256)","swc-id":"101","title":"Integer Underflow","type":"Warning"},{"address":725,"contract":"Unknown","debug":"<DEBUG-DATA>","description":"This binary add operation can result in integer overflow.\n","function":"sendeth(address,uint256)","swc-id":"101","title":"Integer Overflow","type":"Warning"}],"success":true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 567, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The subtraction can result in an integer underflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 750, |
||||
"max_gas_used": 1035, |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 649, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The subtraction can result in an integer underflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 1283, |
||||
"max_gas_used": 1758, |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 725, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This binary add operation can result in integer overflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 6806, |
||||
"max_gas_used": 27471, |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,42 @@ |
||||
{"error": null, "issues": [{"address": 196, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x633ab5e0", "swc-id": "107", "title": "Message call to external contract", "type": "Informational"}, {"address": 285, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe3bea282", "swc-id": "107", "title": "Message call to external contract", "type": "Informational"}, {"address": 290, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe3bea282", "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 196, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "_function_0x633ab5e0", |
||||
"swc-id": "107", |
||||
"min_gas_used": 599, |
||||
"max_gas_used": 1210, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 285, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "_function_0xe3bea282", |
||||
"swc-id": "107", |
||||
"min_gas_used": 621, |
||||
"max_gas_used": 1232, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 290, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xe3bea282", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1330, |
||||
"max_gas_used": 35941, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,18 @@ |
||||
{"error": null, "issues": [{"address": 146, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable SUICIDE instruction was detected. The remaining Ether is sent to an address provided as a function argument.\n", "function": "_function_0xcbf0b0c0", "swc-id": "106", "title": "Unchecked SUICIDE", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 146, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable SUICIDE instruction was detected. The remaining Ether is sent to an address provided as a function argument.\n", |
||||
"function": "_function_0xcbf0b0c0", |
||||
"swc-id": "106", |
||||
"min_gas_used": 168, |
||||
"max_gas_used": 263, |
||||
"title": "Unchecked SUICIDE", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
@ -1 +1,42 @@ |
||||
{"error": null, "issues": [{"address": 567, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The subtraction can result in an integer underflow.\n", "function": "sendeth(address,uint256)", "swc-id": "101", "title": "Integer Underflow", "type": "Warning"}, {"address": 649, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The subtraction can result in an integer underflow.\n", "function": "sendeth(address,uint256)", "swc-id": "101", "title": "Integer Underflow", "type": "Warning"}, {"address": 725, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "This binary add operation can result in integer overflow.\n", "function": "sendeth(address,uint256)", "swc-id": "101", "title": "Integer Overflow", "type": "Warning"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 567, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The subtraction can result in an integer underflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 750, |
||||
"max_gas_used": 1035, |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 649, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The subtraction can result in an integer underflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 1283, |
||||
"max_gas_used": 1758, |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 725, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This binary add operation can result in integer overflow.\n", |
||||
"function": "sendeth(address,uint256)", |
||||
"swc-id": "101", |
||||
"min_gas_used": 6806, |
||||
"max_gas_used": 27471, |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
Loading…
Reference in new issue