Balance modelling and symbolic sender variables (#1025)

* add actor address to symbolic

This will allow us to simulate semi-symbolic transaction senders

* add value transfer to transaction global state creation

* add proper balance tracking to world state and account

* use address value vs string

* disable actor address variable

* use address directly

* allow balance functions with int types

* use value as getters since bitvecs aren't hashable

* implement correct value transfer for suicide

* use actor from actor pool

* allow use of Or with *arg pattern

* use bitvec instead of strings

* add dynamic balance implementation to state datamodels

* cleanup svm interface

* use balance lambda in suicide op implementation

* use bitvec instead of string address

* update world state and account creation in symbolic

* update tests to include overflow results

* apply style rules

* ignore previous open states for now

* update native test to conform to new laser interface

* fix incorrect types in the symbolic virtual machine

* allow multiple types as input for address in account

* fix type hint in symbolic.py

* get int out of string in call

* fix type in call op implementation

* adapt test_transaction to conform to new laser interface

* use static address to keep contracts from trying to enter themselves
and make address type more dynamic

* update evm test to conform to new laser interface

* implement suicide to uncreated account

* apply style rules

* dynamically create colormap

This removes the need for a globally maintained accountlist

* get value out of address

* add accounts getter

* change symbolic test call to be valid with respect to the world
state and account apis

* remove dependency on globally recorded accounts

* fix typing issues

* fix type annotations in symbolic.py

* fix remaining mypy warnings

* simplify assertion check

* execute lambda to get balance

* make variable name plural

* add documentation to svm constructor

* use list comprehension to make code cleaner

* remove comment

* change variable name to plural

* remove commented code

* change variable name to conform to changed interface
pull/1039/head
JoranHonig 6 years ago committed by Nikhil Parasaram
parent 1a9d0cdd0e
commit a9671de8a3
  1. 23
      mythril/analysis/callgraph.py
  2. 53
      mythril/analysis/symbolic.py
  3. 20
      mythril/laser/ethereum/call.py
  4. 28
      mythril/laser/ethereum/instructions.py
  5. 46
      mythril/laser/ethereum/state/account.py
  6. 2
      mythril/laser/ethereum/state/environment.py
  7. 2
      mythril/laser/ethereum/state/global_state.py
  8. 57
      mythril/laser/ethereum/state/world_state.py
  9. 89
      mythril/laser/ethereum/svm.py
  10. 31
      mythril/laser/ethereum/transaction/symbolic.py
  11. 16
      mythril/laser/ethereum/transaction/transaction_models.py
  12. 7
      mythril/laser/smt/bool.py
  13. 23
      tests/laser/evm_testsuite/evm_test.py
  14. 12
      tests/laser/test_transaction.py
  15. 6
      tests/laser/transaction/symbolic_test.py
  16. 19
      tests/native_test.py
  17. 2
      tests/report_test.py
  18. 244
      tests/testdata/outputs_expected/calls.sol.o.json
  19. 2
      tests/testdata/outputs_expected/calls.sol.o.jsonv2
  20. 36
      tests/testdata/outputs_expected/environments.sol.o.json
  21. 34
      tests/testdata/outputs_expected/environments.sol.o.markdown
  22. 30
      tests/testdata/outputs_expected/environments.sol.o.text
  23. 12
      tests/testdata/outputs_expected/ether_send.sol.o.jsonv2
  24. 2
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.jsonv2
  25. 12
      tests/testdata/outputs_expected/metacoin.sol.o.jsonv2
  26. 12
      tests/testdata/outputs_expected/nonascii.sol.o.jsonv2
  27. 13
      tests/testdata/outputs_expected/overflow.sol.o.json
  28. 17
      tests/testdata/outputs_expected/overflow.sol.o.jsonv2
  29. 13
      tests/testdata/outputs_expected/overflow.sol.o.markdown
  30. 11
      tests/testdata/outputs_expected/overflow.sol.o.text
  31. 166
      tests/testdata/outputs_expected/rubixi.sol.o.json
  32. 238
      tests/testdata/outputs_expected/rubixi.sol.o.markdown
  33. 177
      tests/testdata/outputs_expected/rubixi.sol.o.text
  34. 13
      tests/testdata/outputs_expected/underflow.sol.o.json
  35. 17
      tests/testdata/outputs_expected/underflow.sol.o.jsonv2
  36. 13
      tests/testdata/outputs_expected/underflow.sol.o.markdown
  37. 11
      tests/testdata/outputs_expected/underflow.sol.o.text
  38. 46
      tests/testdata/outputs_expected/weak_random.sol.o.json
  39. 62
      tests/testdata/outputs_expected/weak_random.sol.o.markdown
  40. 46
      tests/testdata/outputs_expected/weak_random.sol.o.text

@ -125,7 +125,7 @@ phrack_color = {
} }
def extract_nodes(statespace, color_map): def extract_nodes(statespace):
""" """
:param statespace: :param statespace:
@ -133,6 +133,7 @@ def extract_nodes(statespace, color_map):
:return: :return:
""" """
nodes = [] nodes = []
color_map = {}
for node_key in statespace.nodes: for node_key in statespace.nodes:
node = statespace.nodes[node_key] node = statespace.nodes[node_key]
instructions = [state.get_current_instruction() for state in node.states] instructions = [state.get_current_instruction() for state in node.states]
@ -164,10 +165,16 @@ def extract_nodes(statespace, color_map):
else "\n".join(code_split[:6]) + "\n(click to expand +)" else "\n".join(code_split[:6]) + "\n(click to expand +)"
) )
if node.get_cfg_dict()["contract_name"] not in color_map.keys():
color = default_colors[len(color_map) % len(default_colors)]
color_map[node.get_cfg_dict()["contract_name"]] = color
nodes.append( nodes.append(
{ {
"id": str(node_key), "id": str(node_key),
"color": color_map[node.get_cfg_dict()["contract_name"]], "color": color_map.get(
node.get_cfg_dict()["contract_name"], default_colors[0]
),
"size": 150, "size": 150,
"fullLabel": "\n".join(code_split), "fullLabel": "\n".join(code_split),
"label": truncated_code, "label": truncated_code,
@ -231,22 +238,12 @@ def generate_graph(
template = env.get_template("callgraph.html") template = env.get_template("callgraph.html")
graph_opts = default_opts graph_opts = default_opts
accounts = statespace.accounts
if phrackify:
color_map = {accounts[k].contract_name: phrack_color for k in accounts}
graph_opts.update(phrack_opts)
else:
color_map = {
accounts[k].contract_name: default_colors[i % len(default_colors)]
for i, k in enumerate(accounts)
}
graph_opts["physics"]["enabled"] = physics graph_opts["physics"]["enabled"] = physics
return template.render( return template.render(
title=title, title=title,
nodes=extract_nodes(statespace, color_map), nodes=extract_nodes(statespace),
edges=extract_edges(statespace), edges=extract_edges(statespace),
phrackify=phrackify, phrackify=phrackify,
opts=graph_opts, opts=graph_opts,

@ -2,22 +2,22 @@
purposes.""" purposes."""
import copy import copy
from ethereum.utils import mk_contract_address
from mythril.analysis.security import get_detection_module_hooks, get_detection_modules from mythril.analysis.security import get_detection_module_hooks, get_detection_modules
from mythril.laser.ethereum import svm from mythril.laser.ethereum import svm
from mythril.laser.ethereum.plugins.plugin_factory import PluginFactory
from mythril.laser.ethereum.plugins.plugin_loader import LaserPluginLoader
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.strategy.basic import ( from mythril.laser.ethereum.strategy.basic import (
BreadthFirstSearchStrategy, BreadthFirstSearchStrategy,
DepthFirstSearchStrategy, DepthFirstSearchStrategy,
ReturnRandomNaivelyStrategy, ReturnRandomNaivelyStrategy,
ReturnWeightedRandomStrategy, ReturnWeightedRandomStrategy,
BasicSearchStrategy,
) )
from mythril.laser.ethereum.transaction.symbolic import CREATOR_ADDRESS from mythril.laser.smt import symbol_factory, BitVec
from typing import Union, List, Dict, Type
from mythril.laser.ethereum.plugins.plugin_factory import PluginFactory
from mythril.laser.ethereum.plugins.plugin_loader import LaserPluginLoader
from mythril.solidity.soliditycontract import EVMContract, SolidityContract from mythril.solidity.soliditycontract import EVMContract, SolidityContract
from .ops import Call, SStore, VarType, get_variable from .ops import Call, SStore, VarType, get_variable
@ -32,7 +32,7 @@ class SymExecWrapper:
def __init__( def __init__(
self, self,
contract, contract,
address, address: Union[int, str, BitVec],
strategy, strategy,
dynloader=None, dynloader=None,
max_depth=22, max_depth=22,
@ -55,8 +55,13 @@ class SymExecWrapper:
:param transaction_count: :param transaction_count:
:param modules: :param modules:
""" """
if isinstance(address, str):
address = symbol_factory.BitVecVal(int(address, 16), 256)
if isinstance(address, int):
address = symbol_factory.BitVecVal(address, 256)
if strategy == "dfs": if strategy == "dfs":
s_strategy = DepthFirstSearchStrategy s_strategy = DepthFirstSearchStrategy # type: Type[BasicSearchStrategy]
elif strategy == "bfs": elif strategy == "bfs":
s_strategy = BreadthFirstSearchStrategy s_strategy = BreadthFirstSearchStrategy
elif strategy == "naive-random": elif strategy == "naive-random":
@ -66,19 +71,11 @@ class SymExecWrapper:
else: else:
raise ValueError("Invalid strategy argument supplied") raise ValueError("Invalid strategy argument supplied")
account = Account(
address,
contract.disassembly,
dynamic_loader=dynloader,
contract_name=contract.name,
)
requires_statespace = ( requires_statespace = (
compulsory_statespace or len(get_detection_modules("post", modules)) > 0 compulsory_statespace or len(get_detection_modules("post", modules)) > 0
) )
self.accounts = {address: account}
self.laser = svm.LaserEVM( self.laser = svm.LaserEVM(
self.accounts,
dynamic_loader=dynloader, dynamic_loader=dynloader,
max_depth=max_depth, max_depth=max_depth,
execution_timeout=execution_timeout, execution_timeout=execution_timeout,
@ -111,12 +108,16 @@ class SymExecWrapper:
creation_code=contract.creation_code, contract_name=contract.name creation_code=contract.creation_code, contract_name=contract.name
) )
else: else:
self.laser.sym_exec(address) account = Account(
created_address = "0x" + str(mk_contract_address(CREATOR_ADDRESS, 0).hex()) address,
for key, value in self.laser.world_state.accounts.items(): contract.disassembly,
if created_address == value.address: dynamic_loader=dynloader,
contract.code = value.code.bytecode contract_name=contract.name,
break concrete_storage=False,
)
world_state = WorldState()
world_state.put_account(account)
self.laser.sym_exec(world_state=world_state, target_address=address.value)
if not requires_statespace: if not requires_statespace:
return return
@ -126,8 +127,8 @@ class SymExecWrapper:
# Generate lists of interesting operations # Generate lists of interesting operations
self.calls = [] self.calls = [] # type: List[Call]
self.sstors = {} self.sstors = {} # type: Dict[int, Dict[str, List[SStore]]]
for key in self.nodes: for key in self.nodes:
@ -204,7 +205,7 @@ class SymExecWrapper:
elif op == "SSTORE": elif op == "SSTORE":
stack = copy.copy(state.mstate.stack) stack = copy.copy(state.mstate.stack)
address = state.environment.active_account.address address = state.environment.active_account.address.value
index, value = stack.pop(), stack.pop() index, value = stack.pop(), stack.pop()

@ -3,13 +3,12 @@ instructions.py to get the necessary elements from the stack and determine the
parameters for the new global state.""" parameters for the new global state."""
import logging import logging
import re
from typing import Union, List, cast, Callable from typing import Union, List, cast, Callable
from z3 import Z3Exception
from mythril.laser.smt import BitVec import mythril.laser.ethereum.util as util
from mythril.laser.ethereum import natives from mythril.laser.ethereum import natives
from mythril.laser.ethereum.gas import OPCODE_GAS from mythril.laser.ethereum.gas import OPCODE_GAS
from mythril.laser.smt import simplify, Expression, symbol_factory
import mythril.laser.ethereum.util as util
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import ( from mythril.laser.ethereum.state.calldata import (
BaseCalldata, BaseCalldata,
@ -17,8 +16,9 @@ from mythril.laser.ethereum.state.calldata import (
ConcreteCalldata, ConcreteCalldata,
) )
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.smt import BitVec
from mythril.laser.smt import simplify, Expression, symbol_factory
from mythril.support.loader import DynLoader from mythril.support.loader import DynLoader
import re
""" """
This module contains the business logic used by Instruction in instructions.py This module contains the business logic used by Instruction in instructions.py
@ -96,7 +96,7 @@ def get_callee_address(
# attempt to read the contract address from instance storage # attempt to read the contract address from instance storage
try: try:
callee_address = dynamic_loader.read_storage( callee_address = dynamic_loader.read_storage(
environment.active_account.address, index str(hex(environment.active_account.address.value)), index
) )
# TODO: verify whether this happens or not # TODO: verify whether this happens or not
except: except:
@ -124,7 +124,7 @@ def get_callee_account(
accounts = global_state.accounts accounts = global_state.accounts
try: try:
return global_state.accounts[callee_address] return global_state.accounts[int(callee_address, 16)]
except KeyError: except KeyError:
# We have a valid call address, but contract is not in the modules list # We have a valid call address, but contract is not in the modules list
log.debug("Module with address " + callee_address + " not loaded.") log.debug("Module with address " + callee_address + " not loaded.")
@ -145,7 +145,11 @@ def get_callee_account(
log.debug("Dependency loaded: " + callee_address) log.debug("Dependency loaded: " + callee_address)
callee_account = Account( callee_account = Account(
callee_address, code, callee_address, dynamic_loader=dynamic_loader symbol_factory.BitVecVal(int(callee_address, 16), 256),
code,
callee_address,
dynamic_loader=dynamic_loader,
balances=global_state.world_state.balances,
) )
accounts[callee_address] = callee_account accounts[callee_address] = callee_account

@ -1520,7 +1520,7 @@ class Instruction:
global_state.environment.active_account global_state.environment.active_account
) )
global_state.accounts[ global_state.accounts[
global_state.environment.active_account.address global_state.environment.active_account.address.value
] = global_state.environment.active_account ] = global_state.environment.active_account
global_state.environment.active_account.storage[index] = ( global_state.environment.active_account.storage[index] = (
@ -1756,31 +1756,19 @@ class Instruction:
:param global_state: :param global_state:
""" """
target = global_state.mstate.stack.pop() target = global_state.mstate.stack.pop()
account_created = False transfer_amount = global_state.environment.active_account.balance()
# Often the target of the suicide instruction will be symbolic # Often the target of the suicide instruction will be symbolic
# If it isn't then well transfer the balance to the indicated contract # If it isn't then we'll transfer the balance to the indicated contract
if isinstance(target, BitVec) and not target.symbolic: global_state.world_state[target].add_balance(transfer_amount)
target = "0x" + hex(target.value)[-40:]
if isinstance(target, str):
try:
global_state.world_state[
target
].balance += global_state.environment.active_account.balance
except KeyError:
global_state.world_state.create_account(
address=target,
balance=global_state.environment.active_account.balance,
)
account_created = True
global_state.environment.active_account = deepcopy( global_state.environment.active_account = deepcopy(
global_state.environment.active_account global_state.environment.active_account
) )
global_state.accounts[ global_state.accounts[
global_state.environment.active_account.address global_state.environment.active_account.address.value
] = global_state.environment.active_account ] = global_state.environment.active_account
global_state.environment.active_account.balance = 0 global_state.environment.active_account.set_balance(0)
global_state.environment.active_account.deleted = True global_state.environment.active_account.deleted = True
global_state.current_transaction.end(global_state) global_state.current_transaction.end(global_state)
@ -1865,9 +1853,7 @@ class Instruction:
gas_price=environment.gasprice, gas_price=environment.gasprice,
gas_limit=gas, gas_limit=gas,
origin=environment.origin, origin=environment.origin,
caller=symbol_factory.BitVecVal( caller=environment.active_account.address,
int(environment.active_account.address, 16), 256
),
callee_account=callee_account, callee_account=callee_account,
call_data=call_data, call_data=call_data,
call_value=value, call_value=value,

@ -7,6 +7,7 @@ from typing import Any, Dict, KeysView, Union
from z3 import ExprRef from z3 import ExprRef
from mythril.laser.smt import Array, symbol_factory, BitVec
from mythril.disassembler.disassembly import Disassembly from mythril.disassembler.disassembly import Disassembly
from mythril.laser.smt import symbol_factory from mythril.laser.smt import symbol_factory
@ -30,7 +31,7 @@ class Storage:
except KeyError: except KeyError:
if ( if (
self.address self.address
and int(self.address[2:], 16) != 0 and self.address.value != 0
and (self.dynld and self.dynld.storage_loading) and (self.dynld and self.dynld.storage_loading)
): ):
try: try:
@ -74,10 +75,10 @@ class Account:
def __init__( def __init__(
self, self,
address: str, address: Union[BitVec, str],
code=None, code=None,
contract_name="unknown", contract_name="unknown",
balance=None, balances: Array = None,
concrete_storage=False, concrete_storage=False,
dynamic_loader=None, dynamic_loader=None,
) -> None: ) -> None:
@ -91,36 +92,51 @@ class Account:
""" """
self.nonce = 0 self.nonce = 0
self.code = code or Disassembly("") self.code = code or Disassembly("")
self.balance = ( self.address = (
balance address
if balance if isinstance(address, BitVec)
else symbol_factory.BitVecSym("{}_balance".format(address), 256) else symbol_factory.BitVecVal(int(address, 16), 256)
) )
self.storage = Storage( self.storage = Storage(
concrete_storage, address=address, dynamic_loader=dynamic_loader concrete_storage, address=self.address, dynamic_loader=dynamic_loader
) )
# Metadata # Metadata
self.address = address
self.contract_name = contract_name self.contract_name = contract_name
self.deleted = False self.deleted = False
self._balances = balances
self.balance = lambda: self._balances[self.address]
def __str__(self) -> str: def __str__(self) -> str:
return str(self.as_dict) return str(self.as_dict)
def set_balance(self, balance: ExprRef) -> None: def set_balance(self, balance: Union[int, BitVec]) -> None:
""" """
:param balance: :param balance:
""" """
self.balance = balance balance = (
symbol_factory.BitVecVal(balance, 256)
if isinstance(balance, int)
else balance
)
assert self._balances is not None
self._balances[self.address] = balance
def add_balance(self, balance: ExprRef) -> None: def add_balance(self, balance: Union[int, BitVec]) -> None:
""" """
:param balance: :param balance:
""" """
self.balance += balance balance = (
symbol_factory.BitVecVal(balance, 256)
if isinstance(balance, int)
else balance
)
self._balances[self.address] += balance
@property @property
def as_dict(self) -> Dict: def as_dict(self) -> Dict:
@ -131,7 +147,7 @@ class Account:
return { return {
"nonce": self.nonce, "nonce": self.nonce,
"code": self.code, "code": self.code,
"balance": self.balance, "balance": self.balance(),
"storage": self.storage, "storage": self.storage,
} }
@ -139,8 +155,8 @@ class Account:
new_account = Account( new_account = Account(
address=self.address, address=self.address,
code=self.code, code=self.code,
balance=self.balance,
contract_name=self.contract_name, contract_name=self.contract_name,
balances=self._balances,
) )
new_account.storage = deepcopy(self.storage) new_account.storage = deepcopy(self.storage)
new_account.code = self.code new_account.code = self.code

@ -39,7 +39,7 @@ class Environment:
self.active_account = active_account self.active_account = active_account
self.active_function_name = "" self.active_function_name = ""
self.address = symbol_factory.BitVecVal(int(active_account.address, 16), 256) self.address = active_account.address
# Ib # Ib
self.code = active_account.code if code is None else code self.code = active_account.code if code is None else code

@ -77,7 +77,7 @@ class GlobalState:
:return: :return:
""" """
return self.world_state.accounts return self.world_state._accounts
# TODO: remove this, as two instructions are confusing # TODO: remove this, as two instructions are confusing
def get_current_instruction(self) -> Dict: def get_current_instruction(self) -> Dict:

@ -2,6 +2,8 @@
from copy import copy from copy import copy
from random import randint from random import randint
from typing import Dict, List, Iterator, Optional, TYPE_CHECKING from typing import Dict, List, Iterator, Optional, TYPE_CHECKING
from mythril.laser.smt import symbol_factory, Array, BitVec
from ethereum.utils import mk_contract_address from ethereum.utils import mk_contract_address
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.annotation import StateAnnotation from mythril.laser.ethereum.state.annotation import StateAnnotation
@ -22,18 +24,29 @@ class WorldState:
:param transaction_sequence: :param transaction_sequence:
:param annotations: :param annotations:
""" """
self.accounts = {} # type: Dict[str, Account] self._accounts = {} # type: Dict[int, Account]
self.balances = Array("balance", 256, 256)
self.node = None # type: Optional['Node'] self.node = None # type: Optional['Node']
self.transaction_sequence = transaction_sequence or [] self.transaction_sequence = transaction_sequence or []
self._annotations = annotations or [] self._annotations = annotations or []
def __getitem__(self, item: str) -> Account: @property
def accounts(self):
return self._accounts
def __getitem__(self, item: BitVec) -> Account:
"""Gets an account from the worldstate using item as key. """Gets an account from the worldstate using item as key.
:param item: Address of the account to get :param item: Address of the account to get
:return: Account associated with the address :return: Account associated with the address
""" """
return self.accounts[item] try:
return self._accounts[item.value]
except KeyError:
new_account = Account(address=item, code=None, balances=self.balances)
self._accounts[item.value] = new_account
return new_account
def __copy__(self) -> "WorldState": def __copy__(self) -> "WorldState":
""" """
@ -45,7 +58,9 @@ class WorldState:
transaction_sequence=self.transaction_sequence[:], transaction_sequence=self.transaction_sequence[:],
annotations=new_annotations, annotations=new_annotations,
) )
new_world_state.accounts = copy(self.accounts) new_world_state.balances = copy(self.balances)
for account in self._accounts.values():
new_world_state.put_account(copy(account))
new_world_state.node = self.node new_world_state.node = self.node
return new_world_state return new_world_state
@ -65,14 +80,22 @@ class WorldState:
:param dynamic_loader: used for dynamically loading storage from the block chain :param dynamic_loader: used for dynamically loading storage from the block chain
:return: The new account :return: The new account
""" """
address = address if address else self._generate_new_address(creator) address = (
symbol_factory.BitVecVal(address, 256)
if address
else self._generate_new_address(creator)
)
new_account = Account( new_account = Account(
address, address=address,
balance=balance, balances=self.balances,
dynamic_loader=dynamic_loader, dynamic_loader=dynamic_loader,
concrete_storage=concrete_storage, concrete_storage=concrete_storage,
) )
self._put_account(new_account) if balance:
new_account.set_balance(symbol_factory.BitVecVal(balance, 256))
self.put_account(new_account)
return new_account return new_account
def create_initialized_contract_account(self, contract_code, storage) -> None: def create_initialized_contract_account(self, contract_code, storage) -> None:
@ -86,10 +109,10 @@ class WorldState:
""" """
# TODO: Add type hints # TODO: Add type hints
new_account = Account( new_account = Account(
self._generate_new_address(), code=contract_code, balance=0 self._generate_new_address(), code=contract_code, balances=self.balances
) )
new_account.storage = storage new_account.storage = storage
self._put_account(new_account) self.put_account(new_account)
def annotate(self, annotation: StateAnnotation) -> None: def annotate(self, annotation: StateAnnotation) -> None:
""" """
@ -116,22 +139,24 @@ class WorldState:
""" """
return filter(lambda x: isinstance(x, annotation_type), self.annotations) return filter(lambda x: isinstance(x, annotation_type), self.annotations)
def _generate_new_address(self, creator=None) -> str: def _generate_new_address(self, creator=None) -> BitVec:
"""Generates a new address for the global state. """Generates a new address for the global state.
:return: :return:
""" """
if creator: if creator:
# TODO: Use nounce # TODO: Use nounce
return "0x" + str(mk_contract_address(creator, 0).hex()) address = "0x" + str(mk_contract_address(creator, 0).hex())
return symbol_factory.BitVecVal(int(address, 16), 256)
while True: while True:
address = "0x" + "".join([str(hex(randint(0, 16)))[-1] for _ in range(40)]) address = "0x" + "".join([str(hex(randint(0, 16)))[-1] for _ in range(40)])
if address not in self.accounts.keys(): if address not in self._accounts.keys():
return address return symbol_factory.BitVecVal(int(address, 16), 256)
def _put_account(self, account: Account) -> None: def put_account(self, account: Account) -> None:
""" """
:param account: :param account:
""" """
self.accounts[account.address] = account self._accounts[account.address.value] = account
account._balances = self.balances

@ -9,12 +9,12 @@ from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType
from mythril.laser.ethereum.evm_exceptions import StackUnderflowException from mythril.laser.ethereum.evm_exceptions import StackUnderflowException
from mythril.laser.ethereum.evm_exceptions import VmException from mythril.laser.ethereum.evm_exceptions import VmException
from mythril.laser.ethereum.instructions import Instruction from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.iprof import InstructionProfiler
from mythril.laser.ethereum.plugins.signals import PluginSkipWorldState
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy
from mythril.laser.ethereum.time_handler import time_handler from mythril.laser.ethereum.time_handler import time_handler
from mythril.laser.ethereum.plugins.signals import PluginSkipWorldState
from mythril.laser.ethereum.transaction import ( from mythril.laser.ethereum.transaction import (
ContractCreationTransaction, ContractCreationTransaction,
TransactionEndSignal, TransactionEndSignal,
@ -22,7 +22,7 @@ from mythril.laser.ethereum.transaction import (
execute_contract_creation, execute_contract_creation,
execute_message_call, execute_message_call,
) )
from mythril.laser.ethereum.iprof import InstructionProfiler from mythril.laser.smt import symbol_factory
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -46,7 +46,6 @@ class LaserEVM:
def __init__( def __init__(
self, self,
accounts: Dict[str, Account],
dynamic_loader=None, dynamic_loader=None,
max_depth=float("inf"), max_depth=float("inf"),
execution_timeout=60, execution_timeout=60,
@ -57,21 +56,18 @@ class LaserEVM:
enable_iprof=False, enable_iprof=False,
) -> None: ) -> None:
""" """
Initializes the laser evm object
:param accounts:
:param dynamic_loader: :param dynamic_loader: Loads data from chain
:param max_depth: :param max_depth: Maximum execution depth this vm should execute
:param execution_timeout: :param execution_timeout: Time to take for execution
:param create_timeout: :param create_timeout: Time to take for contract creation
:param strategy: :param strategy: Execution search strategy
:param transaction_count: :param transaction_count: The amount of transactions to execute
:param requires_statespace: Variable indicating whether the statespace should be recorded
:param enable_iprof: Variable indicating whether instruction profiling should be turned on
""" """
world_state = WorldState() self.open_states = [] # type: List[WorldState]
world_state.accounts = accounts
# this sets the initial world state
self.world_state = world_state
self.open_states = [world_state]
self.total_states = 0 self.total_states = 0
self.dynamic_loader = dynamic_loader self.dynamic_loader = dynamic_loader
@ -106,23 +102,30 @@ class LaserEVM:
log.info("LASER EVM initialized with dynamic loader: " + str(dynamic_loader)) log.info("LASER EVM initialized with dynamic loader: " + str(dynamic_loader))
@property
def accounts(self) -> Dict[str, Account]:
"""
:return:
"""
return self.world_state.accounts
def sym_exec( def sym_exec(
self, main_address=None, creation_code=None, contract_name=None self,
world_state: WorldState = None,
target_address: int = None,
creation_code: str = None,
contract_name: str = None,
) -> None: ) -> None:
""" Starts symbolic execution
There are two modes of execution.
Either we analyze a preconfigured configuration, in which case the world_state and target_address variables
must be supplied.
Or we execute the creation code of a contract, in which case the creation code and desired name of that
contract should be provided.
:param world_state The world state configuration from which to perform analysis
:param target_address The address of the contract account in the world state which analysis should target
:param creation_code The creation code to create the target contract in the symbolic environment
:param contract_name The name that the created account should be associated with
""" """
pre_configuration_mode = world_state is not None and target_address is not None
scratch_mode = creation_code is not None and contract_name is not None
if pre_configuration_mode == scratch_mode:
raise ValueError("Symbolic execution started with invalid parameters")
:param main_address:
:param creation_code:
:param contract_name:
"""
log.debug("Starting LASER execution") log.debug("Starting LASER execution")
for hook in self._start_sym_exec_hooks: for hook in self._start_sym_exec_hooks:
hook() hook()
@ -130,11 +133,12 @@ class LaserEVM:
time_handler.start_execution(self.execution_timeout) time_handler.start_execution(self.execution_timeout)
self.time = datetime.now() self.time = datetime.now()
if main_address: if pre_configuration_mode:
log.info("Starting message call transaction to {}".format(main_address)) self.open_states = [world_state]
self._execute_transactions(main_address) log.info("Starting message call transaction to {}".format(target_address))
self._execute_transactions(symbol_factory.BitVecVal(target_address, 256))
elif creation_code: elif scratch_mode:
log.info("Starting contract creation transaction") log.info("Starting contract creation transaction")
created_account = execute_contract_creation( created_account = execute_contract_creation(
self, creation_code, contract_name self, creation_code, contract_name
@ -355,7 +359,7 @@ class LaserEVM:
if not revert_changes: if not revert_changes:
return_global_state.world_state = copy(global_state.world_state) return_global_state.world_state = copy(global_state.world_state)
return_global_state.environment.active_account = global_state.accounts[ return_global_state.environment.active_account = global_state.accounts[
return_global_state.environment.active_account.address return_global_state.environment.active_account.address.value
] ]
# Execute the post instruction handler # Execute the post instruction handler
@ -389,19 +393,6 @@ class LaserEVM:
self._new_node_state( self._new_node_state(
state, JumpType.CONDITIONAL, state.mstate.constraints[-1] state, JumpType.CONDITIONAL, state.mstate.constraints[-1]
) )
elif opcode in ("CALL", "CALLCODE", "DELEGATECALL", "STATICCALL"):
assert len(new_states) <= 1
for state in new_states:
self._new_node_state(state, JumpType.CALL)
# Keep track of added contracts so the graph can be generated properly
if (
state.environment.active_account.contract_name
not in self.world_state.accounts.keys()
):
self.world_state.accounts[
state.environment.active_account.address
] = state.environment.active_account
elif opcode == "RETURN": elif opcode == "RETURN":
for state in new_states: for state in new_states:
self._new_node_state(state, JumpType.RETURN) self._new_node_state(state, JumpType.RETURN)

@ -2,25 +2,32 @@
symbolic values.""" symbolic values."""
import logging import logging
from mythril.laser.smt import symbol_factory
from mythril.disassembler.disassembly import Disassembly from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.cfg import Node, Edge, JumpType from mythril.laser.ethereum.cfg import Node, Edge, JumpType
from mythril.laser.ethereum.state.calldata import BaseCalldata, SymbolicCalldata
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import SymbolicCalldata
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.transaction.transaction_models import ( from mythril.laser.ethereum.transaction.transaction_models import (
MessageCallTransaction, MessageCallTransaction,
ContractCreationTransaction, ContractCreationTransaction,
get_next_transaction_id, get_next_transaction_id,
BaseTransaction,
) )
from mythril.laser.smt import symbol_factory, Or, BitVec
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
CREATOR_ADDRESS = 0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE CREATOR_ADDRESS = 0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE
ATTACKER_ADDRESS = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF ATTACKER_ADDRESS = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
ACTOR_ADDRESSES = [
symbol_factory.BitVecVal(0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE, 256),
symbol_factory.BitVecVal(0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF, 256),
symbol_factory.BitVecVal(0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEE, 256),
]
def execute_message_call(laser_evm, callee_address: str) -> None: def execute_message_call(laser_evm, callee_address: BitVec) -> None:
"""Executes a message call transaction from all open states. """Executes a message call transaction from all open states.
:param laser_evm: :param laser_evm:
@ -46,7 +53,9 @@ def execute_message_call(laser_evm, callee_address: str) -> None:
origin=symbol_factory.BitVecSym( origin=symbol_factory.BitVecSym(
"origin{}".format(next_transaction_id), 256 "origin{}".format(next_transaction_id), 256
), ),
caller=symbol_factory.BitVecVal(ATTACKER_ADDRESS, 256), caller=symbol_factory.BitVecSym(
"sender_{}".format(next_transaction_id), 256
),
callee_account=open_world_state[callee_address], callee_account=open_world_state[callee_address],
call_data=SymbolicCalldata(next_transaction_id), call_data=SymbolicCalldata(next_transaction_id),
call_value=symbol_factory.BitVecSym( call_value=symbol_factory.BitVecSym(
@ -69,12 +78,14 @@ def execute_contract_creation(
:return: :return:
""" """
# TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
open_states = laser_evm.open_states[:]
del laser_evm.open_states[:] del laser_evm.open_states[:]
new_account = laser_evm.world_state.create_account( world_state = WorldState()
open_states = [world_state]
new_account = world_state.create_account(
0, concrete_storage=True, dynamic_loader=None, creator=CREATOR_ADDRESS 0, concrete_storage=True, dynamic_loader=None, creator=CREATOR_ADDRESS
) )
if contract_name: if contract_name:
new_account.contract_name = contract_name new_account.contract_name = contract_name
@ -104,7 +115,7 @@ def execute_contract_creation(
return new_account return new_account
def _setup_global_state_for_execution(laser_evm, transaction) -> None: def _setup_global_state_for_execution(laser_evm, transaction: BaseTransaction) -> None:
"""Sets up global state and cfg for a transactions execution. """Sets up global state and cfg for a transactions execution.
:param laser_evm: :param laser_evm:
@ -114,6 +125,10 @@ def _setup_global_state_for_execution(laser_evm, transaction) -> None:
global_state = transaction.initial_global_state() global_state = transaction.initial_global_state()
global_state.transaction_stack.append((transaction, None)) global_state.transaction_stack.append((transaction, None))
global_state.mstate.constraints.append(
Or(*[transaction.caller == actor for actor in ACTOR_ADDRESSES])
)
new_node = Node( new_node = Node(
global_state.environment.active_account.contract_name, global_state.environment.active_account.contract_name,
function_name=global_state.environment.active_function_name, function_name=global_state.environment.active_function_name,

@ -111,8 +111,19 @@ class BaseTransaction:
# Initialize the execution environment # Initialize the execution environment
global_state = GlobalState(self.world_state, environment, None) global_state = GlobalState(self.world_state, environment, None)
global_state.environment.active_function_name = active_function global_state.environment.active_function_name = active_function
sender = environment.sender
receiver = environment.active_account.address
value = environment.callvalue
global_state.world_state.balances[sender] -= value
global_state.world_state.balances[receiver] += value
return global_state return global_state
def initial_global_state(self) -> GlobalState:
raise NotImplementedError
class MessageCallTransaction(BaseTransaction): class MessageCallTransaction(BaseTransaction):
"""Transaction object models an transaction.""" """Transaction object models an transaction."""
@ -143,6 +154,7 @@ class MessageCallTransaction(BaseTransaction):
:param revert: :param revert:
""" """
self.return_data = return_data self.return_data = return_data
raise TransactionEndSignal(global_state, revert) raise TransactionEndSignal(global_state, revert)
@ -190,7 +202,9 @@ class ContractCreationTransaction(BaseTransaction):
contract_code = bytes.hex(array.array("B", return_data).tostring()) contract_code = bytes.hex(array.array("B", return_data).tostring())
global_state.environment.active_account.code.assign_bytecode(contract_code) global_state.environment.active_account.code.assign_bytecode(contract_code)
self.return_data = global_state.environment.active_account.address self.return_data = str(
hex(global_state.environment.active_account.address.value)
)
assert global_state.environment.active_account.code.instruction_list != [] assert global_state.environment.active_account.code.instruction_list != []
raise TransactionEndSignal(global_state, revert=revert) raise TransactionEndSignal(global_state, revert=revert)

@ -90,15 +90,16 @@ def And(*args: Union[Bool, bool]) -> Bool:
return Bool(z3.And([a.raw for a in args_list]), union) return Bool(z3.And([a.raw for a in args_list]), union)
def Or(a: Bool, b: Bool) -> Bool: def Or(*args: Union[Bool, bool]) -> Bool:
"""Create an or expression. """Create an or expression.
:param a: :param a:
:param b: :param b:
:return: :return:
""" """
union = a.annotations + b.annotations args_list = [arg if isinstance(arg, Bool) else Bool(arg) for arg in args]
return Bool(z3.Or(a.raw, b.raw), annotations=union) union = [arg.annotations for arg in args_list]
return Bool(z3.Or([a.raw for a in args_list]), annotations=union)
def Not(a: Bool) -> Bool: def Not(a: Bool) -> Bool:

@ -1,8 +1,9 @@
from mythril.laser.ethereum.svm import LaserEVM from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.disassembler.disassembly import Disassembly from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.transaction.concolic import execute_message_call from mythril.laser.ethereum.transaction.concolic import execute_message_call
from mythril.laser.smt import Expression, BitVec from mythril.laser.smt import Expression, BitVec, symbol_factory
from mythril.analysis.solver import get_model from mythril.analysis.solver import get_model
from datetime import datetime from datetime import datetime
@ -82,25 +83,27 @@ def test_vmtest(
# Arrange # Arrange
if test_name == "gasprice": if test_name == "gasprice":
return return
accounts = {}
world_state = WorldState()
for address, details in pre_condition.items(): for address, details in pre_condition.items():
account = Account(address) account = Account(address)
account.code = Disassembly(details["code"][2:]) account.code = Disassembly(details["code"][2:])
account.balance = int(details["balance"], 16)
account.nonce = int(details["nonce"], 16) account.nonce = int(details["nonce"], 16)
world_state.put_account(account)
account.set_balance(int(details["balance"], 16))
accounts[address] = account laser_evm = LaserEVM()
laser_evm.open_states = [world_state]
laser_evm = LaserEVM(accounts)
# Act # Act
laser_evm.time = datetime.now() laser_evm.time = datetime.now()
final_states = execute_message_call( final_states = execute_message_call(
laser_evm, laser_evm,
callee_address=action["address"], callee_address=symbol_factory.BitVecVal(int(action["address"], 16), 256),
caller_address=action["caller"], caller_address=symbol_factory.BitVecVal(int(action["caller"], 16), 256),
origin_address=binascii.a2b_hex(action["origin"][2:]), origin_address=symbol_factory.BitVecVal(int(action["origin"], 16), 256),
code=action["code"][2:], code=action["code"][2:],
gas_limit=int(action["gas"], 16), gas_limit=int(action["gas"], 16),
data=binascii.a2b_hex(action["data"][2:]), data=binascii.a2b_hex(action["data"][2:]),
@ -132,7 +135,7 @@ def test_vmtest(
) )
for address, details in post_condition.items(): for address, details in post_condition.items():
account = world_state[address] account = world_state[symbol_factory.BitVecVal(int(address, 16), 256)]
assert account.nonce == int(details["nonce"], 16) assert account.nonce == int(details["nonce"], 16)
assert account.code.bytecode == details["code"][2:] assert account.code.bytecode == details["code"][2:]

@ -1,6 +1,8 @@
from mythril.disassembler.disassembly import Disassembly from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum import svm from mythril.laser.ethereum import svm
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
import mythril.laser.ethereum.cfg as cfg import mythril.laser.ethereum.cfg as cfg
@ -18,15 +20,17 @@ def test_intercontract_call():
) )
callee_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" callee_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
world_state = WorldState()
caller_account = Account(caller_address, caller_code, contract_name="Caller") caller_account = Account(caller_address, caller_code, contract_name="Caller")
callee_account = Account(callee_address, callee_code, contract_name="Callee") callee_account = Account(callee_address, callee_code, contract_name="Callee")
world_state.put_account(callee_account)
world_state.put_account(caller_account)
accounts = {caller_address: caller_account, callee_address: callee_account} laser = svm.LaserEVM()
laser = svm.LaserEVM(accounts)
# Act # Act
laser.sym_exec(caller_address) laser.sym_exec(world_state=world_state, target_address=int(caller_address, 16))
# Assert # Assert
# Initial node starts in contract caller # Initial node starts in contract caller

@ -9,6 +9,8 @@ from mythril.laser.ethereum.transaction import (
from mythril.laser.ethereum.svm import LaserEVM from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.smt import symbol_factory
import unittest.mock as mock import unittest.mock as mock
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -29,7 +31,7 @@ def test_execute_message_call(mocked_setup: MagicMock):
laser_evm = LaserEVM({}) laser_evm = LaserEVM({})
world_state = WorldState() world_state = WorldState()
world_state.accounts["address"] = Account("address") world_state.put_account(Account("0x0"))
laser_evm.open_states = [world_state] laser_evm.open_states = [world_state]
laser_evm.exec = MagicMock() laser_evm.exec = MagicMock()
@ -37,7 +39,7 @@ def test_execute_message_call(mocked_setup: MagicMock):
mocked_setup.side_effect = _is_message_call mocked_setup.side_effect = _is_message_call
# Act # Act
execute_message_call(laser_evm, "address") execute_message_call(laser_evm, symbol_factory.BitVecVal(0, 256))
# Assert # Assert
# laser_evm.exec.assert_called_once() # laser_evm.exec.assert_called_once()

@ -3,6 +3,7 @@ from mythril.mythril import MythrilDisassembler
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.machine_state import MachineState from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum import svm from mythril.laser.ethereum import svm
from tests import BaseTestCase from tests import BaseTestCase
@ -29,13 +30,6 @@ IDENTITY_TEST[1] = (hex(476934798798347), False)
def _all_info(laser): def _all_info(laser):
accounts = {}
for address, _account in laser.world_state.accounts.items():
account = _account.as_dict
account["code"] = account["code"].instruction_list
account["balance"] = str(account["balance"])
accounts[address] = account
nodes = {} nodes = {}
for uid, node in laser.nodes.items(): for uid, node in laser.nodes.items():
states = [] states = []
@ -66,7 +60,6 @@ def _all_info(laser):
edges = [edge.as_dict for edge in laser.edges] edges = [edge.as_dict for edge in laser.edges]
return { return {
"accounts": accounts,
"nodes": nodes, "nodes": nodes,
"edges": edges, "edges": edges,
"total_states": laser.total_states, "total_states": laser.total_states,
@ -85,13 +78,13 @@ class NativeTests(BaseTestCase):
"""""" """"""
disassembly = SolidityContract( disassembly = SolidityContract(
"./tests/native_tests.sol", "./tests/native_tests.sol",
solc_binary=MythrilDisassembler._init_solc_binary("0.5.0"), solc_binary=MythrilDisassembler._init_solc_binary("0.5.3"),
).disassembly ).disassembly
account = Account("0x0000000000000000000000000000000000000000", disassembly) account = Account("0x0000000000000000000000000000000000000000", disassembly)
accounts = {account.address: account} world_state = WorldState()
world_state.put_account(account)
laser = svm.LaserEVM(accounts, max_depth=100, transaction_count=1) laser = svm.LaserEVM(max_depth=100, transaction_count=1)
laser.sym_exec(account.address) laser.sym_exec(world_state=world_state, target_address=account.address.value)
laser_info = str(_all_info(laser)) laser_info = str(_all_info(laser))

@ -32,7 +32,7 @@ def _generate_report(input_file):
contract = EVMContract(input_file.read_text(), enable_online_lookup=False) contract = EVMContract(input_file.read_text(), enable_online_lookup=False)
sym = SymExecWrapper( sym = SymExecWrapper(
contract, contract,
address=(util.get_indexed_address(0)), address=0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE,
strategy="dfs", strategy="dfs",
execution_timeout=30, execution_timeout=30,
transaction_count=1, transaction_count=1,

@ -1,123 +1,123 @@
{ {
"error":null, "error": null,
"issues":[ "issues": [
{ {
"address":661, "address": 661,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.",
"function":"thisisfine()", "function": "thisisfine()",
"max_gas_used":1254, "max_gas_used": 1254,
"min_gas_used":643, "min_gas_used": 643,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"107", "swc-id": "107",
"title":"External Call To Fixed Address" "title": "External Call To Fixed Address"
}, },
{ {
"address":661, "address": 661,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.",
"function":"thisisfine()", "function": "thisisfine()",
"max_gas_used":35972, "max_gas_used": 35972,
"min_gas_used":1361, "min_gas_used": 1361,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"104", "swc-id": "104",
"title":"Unchecked Call Return Value" "title": "Unchecked Call Return Value"
}, },
{ {
"address":779, "address": 779,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.",
"function":"callstoredaddress()", "function": "callstoredaddress()",
"max_gas_used":1298, "max_gas_used": 1298,
"min_gas_used":687, "min_gas_used": 687,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"107", "swc-id": "107",
"title":"External Call To Fixed Address" "title": "External Call To Fixed Address"
}, },
{ {
"address":779, "address": 779,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.",
"function":"callstoredaddress()", "function": "callstoredaddress()",
"max_gas_used":36016, "max_gas_used": 36016,
"min_gas_used":1405, "min_gas_used": 1405,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"104", "swc-id": "104",
"title":"Unchecked Call Return Value" "title": "Unchecked Call Return Value"
}, },
{ {
"address":858, "address": 858,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.",
"function":"reentrancy()", "function": "reentrancy()",
"max_gas_used":1320, "max_gas_used": 1320,
"min_gas_used":709, "min_gas_used": 709,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"107", "swc-id": "107",
"title":"External Call To Fixed Address" "title": "External Call To Fixed Address"
}, },
{ {
"address":858, "address": 858,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.",
"function":"reentrancy()", "function": "reentrancy()",
"max_gas_used":61052, "max_gas_used": 61052,
"min_gas_used":6441, "min_gas_used": 6441,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"104", "swc-id": "104",
"title":"Unchecked Call Return Value" "title": "Unchecked Call Return Value"
}, },
{ {
"address":869, "address": 869,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The contract account state is changed after an external call. \nConsider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", "description": "The contract account state is changed after an external call. \nConsider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.",
"function":"reentrancy()", "function": "reentrancy()",
"max_gas_used":null, "max_gas_used": null,
"min_gas_used":null, "min_gas_used": null,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"107", "swc-id": "107",
"title":"State change after external call" "title": "State change after external call"
}, },
{ {
"address":912, "address": 912,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state.", "description": "A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state.",
"function":"calluseraddress(address)", "function": "calluseraddress(address)",
"max_gas_used":616, "max_gas_used": 616,
"min_gas_used":335, "min_gas_used": 335,
"severity":"Medium", "severity": "Medium",
"sourceMap":null, "sourceMap": null,
"swc-id":"107", "swc-id": "107",
"title":"External Call To User-Supplied Address" "title": "External Call To User-Supplied Address"
}, },
{ {
"address":912, "address": 912,
"contract":"Unknown", "contract": "Unknown",
"debug":"<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description":"The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.",
"function":"calluseraddress(address)", "function": "calluseraddress(address)",
"max_gas_used":35336, "max_gas_used": 35336,
"min_gas_used":1055, "min_gas_used": 1055,
"severity":"Low", "severity": "Low",
"sourceMap":null, "sourceMap": null,
"swc-id":"104", "swc-id": "104",
"title":"Unchecked Call Return Value" "title": "Unchecked Call Return Value"
} }
], ],
"success":true "success": true
} }

@ -162,4 +162,4 @@
], ],
"sourceType": "raw-bytecode" "sourceType": "raw-bytecode"
} }
] ]

@ -1,36 +0,0 @@
{
"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,34 +0,0 @@
# Analysis results for test-filename.sol
## Integer Overflow
- SWC ID: 101
- Type: Warning
- Contract: Unknown
- Function name: `_function_0x83f12fec`
- PC address: 158
### Description
The arithmetic operation can result in integer overflow.
## Integer Overflow
- SWC ID: 101
- Type: Warning
- Contract: Unknown
- Function name: `_function_0x83f12fec`
- PC address: 278
### Description
The arithmetic operation can result in integer overflow.
## Integer Underflow
- SWC ID: 101
- Type: Warning
- Contract: Unknown
- Function name: `_function_0x83f12fec`
- PC address: 378
### Description
The substraction can result in an integer underflow.

@ -1,30 +0,0 @@
==== Integer Overflow ====
SWC ID: 101
Type: Warning
Contract: Unknown
Function name: _function_0x83f12fec
PC address: 158
The arithmetic operation can result in integer overflow.
--------------------
==== Integer Overflow ====
SWC ID: 101
Type: Warning
Contract: Unknown
Function name: _function_0x83f12fec
PC address: 278
The arithmetic operation can result in integer overflow.
--------------------
==== Integer Underflow ====
SWC ID: 101
Type: Warning
Contract: Unknown
Function name: _function_0x83f12fec
PC address: 378
The substraction can result in an integer underflow.
--------------------

@ -1 +1,11 @@
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x3746c7c2ae7b0d4c3f8b1905df9a7ea169b9f93bec68a10a00b4c9d27a18c6fb"], "sourceType": "raw-bytecode"}] [
{
"issues": [],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x3746c7c2ae7b0d4c3f8b1905df9a7ea169b9f93bec68a10a00b4c9d27a18c6fb"
],
"sourceType": "raw-bytecode"
}
]

@ -94,4 +94,4 @@
], ],
"sourceType": "raw-bytecode" "sourceType": "raw-bytecode"
} }
] ]

@ -1 +1,11 @@
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x0e6f727bb3301e02d3be831bf34357522fd2f1d40e90dff8e2214553b06b5f6c"], "sourceType": "raw-bytecode"}] [
{
"issues": [],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x0e6f727bb3301e02d3be831bf34357522fd2f1d40e90dff8e2214553b06b5f6c"
],
"sourceType": "raw-bytecode"
}
]

@ -1 +1,11 @@
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x11a78eb09819f505ba4f10747e6d1f7a44480e602c67573b7abac2f733a85d93"], "sourceType": "raw-bytecode"}] [
{
"issues": [],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x11a78eb09819f505ba4f10747e6d1f7a44480e602c67573b7abac2f733a85d93"
],
"sourceType": "raw-bytecode"
}
]

@ -26,6 +26,19 @@
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",
"title": "Integer Underflow" "title": "Integer Underflow"
},
{
"address": 725,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The binary addition can overflow.\nThe operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.",
"function": "sendeth(address,uint256)",
"max_gas_used": 78155,
"min_gas_used": 17019,
"severity": "High",
"sourceMap": null,
"swc-id": "101",
"title": "Integer Overflow"
} }
], ],
"success": true "success": true

@ -34,6 +34,23 @@
"severity": "High", "severity": "High",
"swcID": "SWC-101", "swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow" "swcTitle": "Integer Overflow and Underflow"
},
{
"description": {
"head": "The binary addition can overflow.",
"tail": "The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion."
},
"extra": {
"discoveryTime": "<DISCOVERY-TIME-DATA>"
},
"locations": [
{
"sourceMap": "725:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
} }
], ],
"meta": {}, "meta": {},

@ -25,3 +25,16 @@ The operands of the subtraction operation are not sufficiently constrained. The
The binary subtraction can underflow. The binary subtraction can underflow.
The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion. The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.
## Integer Overflow
- SWC ID: 101
- Severity: High
- Contract: Unknown
- Function name: `sendeth(address,uint256)`
- PC address: 725
- Estimated Gas Usage: 17019 - 78155
### Description
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.

@ -20,3 +20,14 @@ The binary subtraction can underflow.
The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion. The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.
-------------------- --------------------
==== Integer Overflow ====
SWC ID: 101
Severity: High
Contract: Unknown
Function name: sendeth(address,uint256)
PC address: 725
Estimated Gas Usage: 17019 - 78155
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.
--------------------

@ -1,166 +0,0 @@
{
"success": true,
"error": null,
"issues": [
{
"title": "Ether send",
"description": "In the function `_function_0x4229616d` a non-zero amount of Ether is sent to an address taken from storage slot 5.\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\n\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.",
"function": "_function_0x4229616d",
"type": "Warning",
"address": 1599,
"debug": "<DEBUG-DATA>"
},
{
"title": "Ether send",
"description": "In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\n\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.",
"function": "_function_0xb4022950",
"type": "Warning",
"address": 1940,
"debug": "<DEBUG-DATA>"
},
{
"title": "Ether send",
"description": "In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\n\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.\nThere is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.",
"function": "_function_0xb4022950",
"type": "Warning",
"address": 2582,
"debug": "<DEBUG-DATA>"
},
{
"title": "Exception state",
"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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ",
"function": "_function_0x57d4021b",
"type": "Informational",
"address": 1653,
"debug": "<DEBUG-DATA>"
},
{
"title": "Exception state",
"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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ",
"function": "_function_0x9dbc4f9b",
"type": "Informational",
"address": 2085,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "fallback",
"type": "Informational",
"address": 3111,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "fallback",
"type": "Informational",
"address": 3140,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "fallback",
"type": "Informational",
"address": 2950,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "fallback",
"type": "Informational",
"address": 1268,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x09dfdc71",
"type": "Informational",
"address": 310,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x09dfdc71",
"type": "Informational",
"address": 1316,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x253459e3",
"type": "Informational",
"address": 1375,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x4229616d",
"type": "Informational",
"address": 1511,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x57d4021b",
"type": "Informational",
"address": 1679,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x6fbaaa1e",
"type": "Informational",
"address": 618,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x8a5fb3ca",
"type": "Informational",
"address": 805,
"debug": "<DEBUG-DATA>"
},
{
"title": "Invariant branch condition",
"description": "Found a conditional jump which always follows the same branch",
"function": "_function_0x9dbc4f9b",
"type": "Informational",
"address": 2187,
"debug": "<DEBUG-DATA>"
},
{
"title": "Unchecked CALL return value",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0x4229616d",
"type": "Informational",
"address": 1599,
"debug": "<DEBUG-DATA>"
},
{
"title": "Unchecked CALL return value",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0xb4022950",
"type": "Informational",
"address": 1940,
"debug": "<DEBUG-DATA>"
},
{
"title": "Unchecked CALL return value",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0xb4022950",
"type": "Informational",
"address": 2582,
"debug": "<DEBUG-DATA>"
}
]
}

@ -1,238 +0,0 @@
# Analysis results for test-filename.sol
## Ether send
- Type: Warning
- Contract: Unknown
- Function name: `_function_0x4229616d`
- PC address: 1599
### Description
In the function `_function_0x4229616d` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
## Ether send
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xb4022950`
- PC address: 1940
### Description
In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
## Ether send
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xb4022950`
- PC address: 2582
### Description
In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
## Exception state
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x57d4021b`
- PC address: 1653
### 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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
## Exception state
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x9dbc4f9b`
- PC address: 2085
### 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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `fallback`
- PC address: 3111
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `fallback`
- PC address: 3140
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `fallback`
- PC address: 2950
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `fallback`
- PC address: 1268
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x09dfdc71`
- PC address: 310
### Description
Found a conditional jump which always follows the same branch, value: False
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x09dfdc71`
- PC address: 1316
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x253459e3`
- PC address: 1375
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x4229616d`
- PC address: 1511
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x57d4021b`
- PC address: 1679
### Description
Found a conditional jump which always follows the same branch, value: True
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x6fbaaa1e`
- PC address: 618
### Description
Found a conditional jump which always follows the same branch, value: False
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x8a5fb3ca`
- PC address: 805
### Description
Found a conditional jump which always follows the same branch, value: False
## Tautology
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x9dbc4f9b`
- PC address: 2187
### Description
Found a conditional jump which always follows the same branch, value: True
## Unchecked CALL return value
- Type: Informational
- Contract: Unknown
- Function name: `_function_0x4229616d`
- PC address: 1599
### Description
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Unchecked CALL return value
- Type: Informational
- Contract: Unknown
- Function name: `_function_0xb4022950`
- PC address: 1940
### Description
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Unchecked CALL return value
- Type: Informational
- Contract: Unknown
- Function name: `_function_0xb4022950`
- PC address: 2582
### Description
The return value of an external call is not checked. Note that execution continue even if the called contract throws.

@ -1,177 +0,0 @@
==== Ether send ====
Type: Warning
Contract: Unknown
Function name: _function_0x4229616d
PC address: 1599
In the function `_function_0x4229616d` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
--------------------
==== Ether send ====
Type: Warning
Contract: Unknown
Function name: _function_0xb4022950
PC address: 1940
In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
--------------------
==== Ether send ====
Type: Warning
Contract: Unknown
Function name: _function_0xb4022950
PC address: 2582
In the function `_function_0xb4022950` a non-zero amount of Ether is sent to an address taken from storage slot 5.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 5. This storage slot can be written to by calling the function `_function_0x67f809e9`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
--------------------
==== Exception state ====
Type: Informational
Contract: Unknown
Function name: _function_0x57d4021b
PC address: 1653
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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
==== Exception state ====
Type: Informational
Contract: Unknown
Function name: _function_0x9dbc4f9b
PC address: 2085
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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: fallback
PC address: 3111
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: fallback
PC address: 3140
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: fallback
PC address: 2950
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: fallback
PC address: 1268
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x09dfdc71
PC address: 310
Found a conditional jump which always follows the same branch, value: False
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x09dfdc71
PC address: 1316
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x253459e3
PC address: 1375
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x4229616d
PC address: 1511
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x57d4021b
PC address: 1679
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x6fbaaa1e
PC address: 618
Found a conditional jump which always follows the same branch, value: False
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x8a5fb3ca
PC address: 805
Found a conditional jump which always follows the same branch, value: False
--------------------
==== Tautology ====
Type: Informational
Contract: Unknown
Function name: _function_0x9dbc4f9b
PC address: 2187
Found a conditional jump which always follows the same branch, value: True
--------------------
==== Unchecked CALL return value ====
Type: Informational
Contract: Unknown
Function name: _function_0x4229616d
PC address: 1599
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------
==== Unchecked CALL return value ====
Type: Informational
Contract: Unknown
Function name: _function_0xb4022950
PC address: 1940
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------
==== Unchecked CALL return value ====
Type: Informational
Contract: Unknown
Function name: _function_0xb4022950
PC address: 2582
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------

@ -26,6 +26,19 @@
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",
"title": "Integer Underflow" "title": "Integer Underflow"
},
{
"address": 725,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The binary addition can overflow.\nThe operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.",
"function": "sendeth(address,uint256)",
"max_gas_used": 52861,
"min_gas_used": 11915,
"severity": "High",
"sourceMap": null,
"swc-id": "101",
"title": "Integer Overflow"
} }
], ],
"success": true "success": true

@ -34,6 +34,23 @@
"severity": "High", "severity": "High",
"swcID": "SWC-101", "swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow" "swcTitle": "Integer Overflow and Underflow"
},
{
"description": {
"head": "The binary addition can overflow.",
"tail": "The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion."
},
"extra": {
"discoveryTime": "<DISCOVERY-TIME-DATA>"
},
"locations": [
{
"sourceMap": "725:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
} }
], ],
"meta": {}, "meta": {},

@ -25,3 +25,16 @@ The operands of the subtraction operation are not sufficiently constrained. The
The binary subtraction can underflow. The binary subtraction can underflow.
The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion. The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.
## Integer Overflow
- SWC ID: 101
- Severity: High
- Contract: Unknown
- Function name: `sendeth(address,uint256)`
- PC address: 725
- Estimated Gas Usage: 11915 - 52861
### Description
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.

@ -20,3 +20,14 @@ The binary subtraction can underflow.
The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion. The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.
-------------------- --------------------
==== Integer Overflow ====
SWC ID: 101
Severity: High
Contract: Unknown
Function name: sendeth(address,uint256)
PC address: 725
Estimated Gas Usage: 11915 - 52861
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.
--------------------

@ -1,46 +0,0 @@
{
"success": true,
"error": null,
"issues": [
{
"title": "Dependence on predictable environment variable",
"description": "In the function `_function_0xe9874106` the following predictable state variables are used to determine Ether recipient:\n- block.coinbase\n",
"function": "_function_0xe9874106",
"type": "Warning",
"address": 1285,
"debug": "<DEBUG-DATA>"
},
{
"title": "Ether send",
"description": "In the function `_function_0xe9874106` a non-zero amount of Ether is sent to an address taken from storage slot 0.\nThere is a check on storage index 0. This storage slot can be written to by calling the function `fallback`.\n\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.\nThere is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.",
"function": "_function_0xe9874106",
"type": "Warning",
"address": 1285,
"debug": "<DEBUG-DATA>"
},
{
"title": "Exception state",
"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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ",
"function": "fallback",
"type": "Informational",
"address": 356,
"debug": "<DEBUG-DATA>"
},
{
"title": "Exception state",
"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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ",
"function": "_function_0xe9874106",
"type": "Informational",
"address": 146,
"debug": "<DEBUG-DATA>"
},
{
"title": "Transaction order dependence",
"description": "A possible transaction order independence vulnerability exists in function _function_0xe9874106. The value or direction of the call statement is determined from a tainted storage location",
"function": "_function_0xe9874106",
"type": "Warning",
"address": 1285,
"debug": "<DEBUG-DATA>"
}
]
}

@ -1,62 +0,0 @@
# Analysis results for test-filename.sol
## Dependence on predictable environment variable
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xe9874106`
- PC address: 1285
### Description
In the function `_function_0xe9874106` the following predictable state variables are used to determine Ether recipient:
- block.coinbase
## Ether send
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xe9874106`
- PC address: 1285
### Description
In the function `_function_0xe9874106` a non-zero amount of Ether is sent to an address taken from storage slot 0.
There is a check on storage index 0. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
## Exception state
- Type: Informational
- Contract: Unknown
- Function name: `fallback`
- PC address: 356
### 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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
## Exception state
- Type: Informational
- Contract: Unknown
- Function name: `_function_0xe9874106`
- PC address: 146
### 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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
## Transaction order dependence
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xe9874106`
- PC address: 1285
### Description
A possible transaction order independence vulnerability exists in function _function_0xe9874106. The value or direction of the call statement is determined from a tainted storage location

@ -1,46 +0,0 @@
==== Dependence on predictable environment variable ====
Type: Warning
Contract: Unknown
Function name: _function_0xe9874106
PC address: 1285
In the function `_function_0xe9874106` the following predictable state variables are used to determine Ether recipient:
- block.coinbase
--------------------
==== Ether send ====
Type: Warning
Contract: Unknown
Function name: _function_0xe9874106
PC address: 1285
In the function `_function_0xe9874106` a non-zero amount of Ether is sent to an address taken from storage slot 0.
There is a check on storage index 0. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
There is a check on storage index 1. This storage slot can be written to by calling the function `fallback`.
--------------------
==== Exception state ====
Type: Informational
Contract: Unknown
Function name: fallback
PC address: 356
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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
==== Exception state ====
Type: Informational
Contract: Unknown
Function name: _function_0xe9874106
PC address: 146
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. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
==== Transaction order dependence ====
Type: Warning
Contract: Unknown
Function name: _function_0xe9874106
PC address: 1285
A possible transaction order independence vulnerability exists in function _function_0xe9874106. The value or direction of the call statement is determined from a tainted storage location
--------------------
Loading…
Cancel
Save