Merge branch 'develop' of github.com:ConsenSys/mythril into fix/timeout

fix/timeout
Nikhil Parasaram 6 years ago
commit 566a994710
  1. 5
      README.md
  2. 29
      mythril/analysis/report.py
  3. 2
      mythril/analysis/security.py
  4. 2
      mythril/analysis/symbolic.py
  5. 4
      mythril/disassembler/asm.py
  6. 389
      mythril/interfaces/cli.py
  7. 8
      mythril/laser/ethereum/gas.py
  8. 61
      mythril/laser/ethereum/instructions.py
  9. 5
      mythril/laser/ethereum/state/memory.py
  10. 1
      mythril/laser/ethereum/taint_analysis.py
  11. 1
      mythril/laser/smt/__init__.py
  12. 38
      mythril/laser/smt/bitvec.py
  13. 16
      mythril/laser/smt/bitvecfunc.py
  14. 5
      mythril/mythril.py
  15. 15
      mythril/solidity/soliditycontract.py
  16. 94
      mythril/support/opcodes.py
  17. 18
      mythril/support/truffle.py
  18. 2
      mythril/version.py
  19. 2
      solidity_examples/WalletLibrary.sol
  20. 10
      solidity_examples/rubixi.sol
  21. 148
      tests/instructions/sar_test.py
  22. 123
      tests/instructions/shl_test.py
  23. 125
      tests/instructions/shr_test.py
  24. 151
      tests/testdata/outputs_expected/calls.sol.o.jsonv2
  25. 10
      tests/testdata/outputs_expected/ether_send.sol.o.jsonv2
  26. 73
      tests/testdata/outputs_expected/exceptions.sol.o.jsonv2
  27. 12
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.json
  28. 68
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.jsonv2
  29. 6
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown
  30. 6
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.text
  31. 10
      tests/testdata/outputs_expected/metacoin.sol.o.jsonv2
  32. 28
      tests/testdata/outputs_expected/multi_contracts.sol.o.jsonv2
  33. 10
      tests/testdata/outputs_expected/nonascii.sol.o.jsonv2
  34. 28
      tests/testdata/outputs_expected/origin.sol.o.jsonv2
  35. 8
      tests/testdata/outputs_expected/overflow.sol.o.json
  36. 43
      tests/testdata/outputs_expected/overflow.sol.o.jsonv2
  37. 4
      tests/testdata/outputs_expected/overflow.sol.o.markdown
  38. 4
      tests/testdata/outputs_expected/overflow.sol.o.text
  39. 58
      tests/testdata/outputs_expected/returnvalue.sol.o.jsonv2
  40. 28
      tests/testdata/outputs_expected/suicide.sol.o.jsonv2
  41. 8
      tests/testdata/outputs_expected/underflow.sol.o.json
  42. 43
      tests/testdata/outputs_expected/underflow.sol.o.jsonv2
  43. 4
      tests/testdata/outputs_expected/underflow.sol.o.markdown
  44. 4
      tests/testdata/outputs_expected/underflow.sol.o.text

@ -12,9 +12,10 @@
[![Sonarcloud - Maintainability](https://sonarcloud.io/api/project_badges/measure?project=mythril&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=mythril) [![Sonarcloud - Maintainability](https://sonarcloud.io/api/project_badges/measure?project=mythril&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=mythril)
[![Downloads](https://pepy.tech/badge/mythril)](https://pepy.tech/project/mythril) [![Downloads](https://pepy.tech/badge/mythril)](https://pepy.tech/project/mythril)
Mythril Classic is an open-source security analysis tool for Ethereum smart contracts. It uses symbolic analysis, taint analysis and control flow checking to detect a variety of security vulnerabilities. Mythril Classic is an open-source security analysis tool for Ethereum smart contracts. It uses symbolic analysis, taint analysis and control flow checking to detect a variety of security vulnerabilities. It's also an experimental tool designed for security pros. If you a smart contract developer you might prefer smoother tools such as:
This is an experimental tool designed for security guys. If you a smart contract developer you might prefer [Truffle Security](https://github.com/ConsenSys/truffle-security) or other convenient tools built on the [MythX API](https://mythx.io). - [Mythos](https://github.com/cleanunicorn/mythos)
- [Truffle Security](https://github.com/ConsenSys/truffle-security)
Whether you want to contribute, need support, or want to learn what we have cooking for the future, our [Discord server](https://discord.gg/E3YrVtG) will serve your needs. Whether you want to contribute, need support, or want to learn what we have cooking for the future, our [Discord server](https://discord.gg/E3YrVtG) will serve your needs.

@ -3,6 +3,7 @@ import logging
import json import json
import operator import operator
from jinja2 import PackageLoader, Environment from jinja2 import PackageLoader, Environment
from typing import Dict, List
import _pysha3 as sha3 import _pysha3 as sha3
import hashlib import hashlib
@ -106,6 +107,17 @@ class Issue:
return issue return issue
def _set_internal_compiler_error(self):
"""
Adds the false positive to description and changes severity to low
"""
self.severity = "Low"
self.description_tail += (
" This issue is reported for internal compiler generated code."
)
self.description = "%s\n%s" % (self.description_head, self.description_tail)
self.code = ""
def add_code_info(self, contract): def add_code_info(self, contract):
""" """
@ -118,6 +130,8 @@ class Issue:
self.filename = codeinfo.filename self.filename = codeinfo.filename
self.code = codeinfo.code self.code = codeinfo.code
self.lineno = codeinfo.lineno self.lineno = codeinfo.lineno
if self.lineno is None:
self._set_internal_compiler_error()
self.source_mapping = codeinfo.solc_mapping self.source_mapping = codeinfo.solc_mapping
else: else:
self.source_mapping = self.address self.source_mapping = self.address
@ -130,7 +144,7 @@ class Report:
loader=PackageLoader("mythril.analysis"), trim_blocks=True loader=PackageLoader("mythril.analysis"), trim_blocks=True
) )
def __init__(self, verbose=False, source=None): def __init__(self, verbose=False, source=None, exceptions=None):
""" """
:param verbose: :param verbose:
@ -140,6 +154,7 @@ class Report:
self.solc_version = "" self.solc_version = ""
self.meta = {} self.meta = {}
self.source = source or Source() self.source = source or Source()
self.exceptions = exceptions or []
def sorted_issues(self): def sorted_issues(self):
""" """
@ -177,6 +192,14 @@ class Report:
result = {"success": True, "error": None, "issues": self.sorted_issues()} result = {"success": True, "error": None, "issues": self.sorted_issues()}
return json.dumps(result, sort_keys=True) return json.dumps(result, sort_keys=True)
def _get_exception_data(self) -> dict:
if not self.exceptions:
return {}
logs = [] # type: List[Dict]
for exception in self.exceptions:
logs += [{"level": "error", "hidden": "true", "error": exception}]
return {"logs": logs}
def as_swc_standard_format(self): def as_swc_standard_format(self):
"""Format defined for integration and correlation. """Format defined for integration and correlation.
@ -211,14 +234,14 @@ class Report:
"extra": {}, "extra": {},
} }
) )
meta_data = self._get_exception_data()
result = [ result = [
{ {
"issues": _issues, "issues": _issues,
"sourceType": "raw-bytecode", "sourceType": "raw-bytecode",
"sourceFormat": "evm-byzantium-bytecode", "sourceFormat": "evm-byzantium-bytecode",
"sourceList": source_list, "sourceList": source_list,
"meta": {}, "meta": meta_data,
} }
] ]

@ -1,7 +1,7 @@
"""This module contains functionality for hooking in detection modules and """This module contains functionality for hooking in detection modules and
executing them.""" executing them."""
from collections import defaultdict from collections import defaultdict
from ethereum.opcodes import opcodes from mythril.support.opcodes import opcodes
from mythril.analysis import modules from mythril.analysis import modules
import pkgutil import pkgutil
import importlib.util import importlib.util

@ -193,7 +193,7 @@ class SymExecWrapper:
) )
elif op == "SSTORE": elif op == "SSTORE":
stack = copy.deepcopy(state.mstate.stack) stack = copy.copy(state.mstate.stack)
address = state.environment.active_account.address address = state.environment.active_account.address
index, value = stack.pop(), stack.pop() index, value = stack.pop(), stack.pop()

@ -4,12 +4,12 @@ code disassembly."""
import re import re
from collections import Generator from collections import Generator
from ethereum.opcodes import opcodes from mythril.support.opcodes import opcodes
regex_PUSH = re.compile(r"^PUSH(\d*)$") regex_PUSH = re.compile(r"^PUSH(\d*)$")
# Additional mnemonic to catch failed assertions # Additional mnemonic to catch failed assertions
opcodes[254] = ["ASSERT_FAIL", 0, 0, 0] opcodes[254] = ("ASSERT_FAIL", 0, 0, 0)
class EvmInstruction: class EvmInstruction:

@ -10,6 +10,7 @@ import json
import logging import logging
import os import os
import sys import sys
import traceback
import coloredlogs import coloredlogs
@ -31,17 +32,47 @@ def exit_with_error(format_, message):
""" """
if format_ == "text" or format_ == "markdown": if format_ == "text" or format_ == "markdown":
log.error(message) log.error(message)
else: elif format_ == "json":
result = {"success": False, "error": str(message), "issues": []} result = {"success": False, "error": str(message), "issues": []}
print(json.dumps(result)) print(json.dumps(result))
else:
result = [
{
"issues": [],
"sourceType": "",
"sourceFormat": "",
"sourceList": [],
"meta": {
"logs": [{"level": "error", "hidden": "true", "error": message}]
},
}
]
print(json.dumps(result))
sys.exit() sys.exit()
def main(): def main() -> None:
"""The main CLI interface entry point.""" """The main CLI interface entry point."""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Security analysis of Ethereum smart contracts" description="Security analysis of Ethereum smart contracts"
) )
create_parser(parser)
# Get config values
args = parser.parse_args()
parse_args(parser=parser, args=args)
if __name__ == "__main__":
main()
def create_parser(parser: argparse.ArgumentParser) -> None:
"""
Creates the parser by setting all the possible arguments
:param parser: The parser
"""
parser.add_argument("solidity_file", nargs="*") parser.add_argument("solidity_file", nargs="*")
commands = parser.add_argument_group("commands") commands = parser.add_argument_group("commands")
@ -227,25 +258,8 @@ def main():
) )
parser.add_argument("--epic", action="store_true", help=argparse.SUPPRESS) parser.add_argument("--epic", action="store_true", help=argparse.SUPPRESS)
# Get config values
args = parser.parse_args()
if args.epic:
path = os.path.dirname(os.path.realpath(__file__))
sys.argv.remove("--epic")
os.system(" ".join(sys.argv) + " | python3 " + path + "/epic.py")
sys.exit()
if args.version:
if args.outform == "json":
print(json.dumps({"version_str": VERSION}))
else:
print("Mythril version {}".format(VERSION))
sys.exit()
# Parse cmdline args
def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace):
if not ( if not (
args.search args.search
or args.hash or args.hash
@ -298,177 +312,119 @@ def main():
"--enable-iprof must be used with one of -g, --graph, -x, --fire-lasers, -j and --statespace-json", "--enable-iprof must be used with one of -g, --graph, -x, --fire-lasers, -j and --statespace-json",
) )
# -- commands --
def quick_commands(args: argparse.Namespace):
if args.hash: if args.hash:
print(Mythril.hash_for_function_signature(args.hash)) print(Mythril.hash_for_function_signature(args.hash))
sys.exit() sys.exit()
try:
# the mythril object should be our main interface def set_config(args: argparse.Namespace):
# infura = None, rpc = None, rpctls = None mythril = Mythril(
# solc_args = None, dynld = None, max_recursion_depth = 12): solv=args.solv,
dynld=args.dynld,
mythril = Mythril( onchain_storage_access=(not args.no_onchain_storage_access),
solv=args.solv, solc_args=args.solc_args,
dynld=args.dynld, enable_online_lookup=args.query_signature,
onchain_storage_access=(not args.no_onchain_storage_access), )
solc_args=args.solc_args, if args.dynld or not args.no_onchain_storage_access and not (args.rpc or args.i):
enable_online_lookup=args.query_signature, mythril.set_api_from_config_path()
if args.address:
# Establish RPC connection if necessary
mythril.set_api_rpc(rpc=args.rpc, rpctls=args.rpctls)
elif args.search or args.contract_hash_to_address:
# Open LevelDB if necessary
mythril.set_api_leveldb(
mythril.leveldb_dir if not args.leveldb_dir else args.leveldb_dir
) )
if ( return mythril
args.dynld
or not args.no_onchain_storage_access
and not (args.rpc or args.i)
):
mythril.set_api_from_config_path()
if args.address:
# Establish RPC connection if necessary
mythril.set_api_rpc(rpc=args.rpc, rpctls=args.rpctls)
elif args.search or args.contract_hash_to_address:
# Open LevelDB if necessary
mythril.set_api_leveldb(
mythril.leveldb_dir if not args.leveldb_dir else args.leveldb_dir
)
if args.search:
# Database search ops
mythril.search_db(args.search)
sys.exit()
if args.contract_hash_to_address: def leveldb_search(mythril: Mythril, args: argparse.Namespace):
# search corresponding address if args.search:
try: # Database search ops
mythril.contract_hash_to_address(args.contract_hash_to_address) mythril.search_db(args.search)
except AddressNotFoundError: sys.exit()
print("Address not found.")
sys.exit() if args.contract_hash_to_address:
# search corresponding address
try:
mythril.contract_hash_to_address(args.contract_hash_to_address)
except AddressNotFoundError:
print("Address not found.")
if args.truffle: sys.exit()
try:
# not really pythonic atm. needs refactoring
mythril.analyze_truffle_project(args)
except FileNotFoundError:
print(
"Build directory not found. Make sure that you start the analysis from the project root, and that 'truffle compile' has executed successfully."
)
sys.exit()
# Load / compile input contracts
address = None def get_code(mythril: Mythril, args: argparse.Namespace):
address = None
if args.code: if args.code:
# Load from bytecode # Load from bytecode
code = args.code[2:] if args.code.startswith("0x") else args.code code = args.code[2:] if args.code.startswith("0x") else args.code
address, _ = mythril.load_from_bytecode(code, args.bin_runtime) address, _ = mythril.load_from_bytecode(code, args.bin_runtime)
elif args.codefile: elif args.codefile:
bytecode = "".join([l.strip() for l in args.codefile if len(l.strip()) > 0]) bytecode = "".join([l.strip() for l in args.codefile if len(l.strip()) > 0])
bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode
address, _ = mythril.load_from_bytecode(bytecode, args.bin_runtime) address, _ = mythril.load_from_bytecode(bytecode, args.bin_runtime)
elif args.address: elif args.address:
# Get bytecode from a contract address # Get bytecode from a contract address
address, _ = mythril.load_from_address(args.address) address, _ = mythril.load_from_address(args.address)
elif args.solidity_file: elif args.solidity_file:
# Compile Solidity source file(s) # Compile Solidity source file(s)
if args.graph and len(args.solidity_file) > 1: if args.graph and len(args.solidity_file) > 1:
exit_with_error(
args.outform,
"Cannot generate call graphs from multiple input files. Please do it one at a time.",
)
address, _ = mythril.load_from_solidity(args.solidity_file) # list of files
else:
exit_with_error( exit_with_error(
args.outform, args.outform,
"No input bytecode. Please provide EVM code via -c BYTECODE, -a ADDRESS, or -i SOLIDITY_FILES", "Cannot generate call graphs from multiple input files. Please do it one at a time.",
) )
address, _ = mythril.load_from_solidity(args.solidity_file) # list of files
else:
exit_with_error(
args.outform,
"No input bytecode. Please provide EVM code via -c BYTECODE, -a ADDRESS, or -i SOLIDITY_FILES",
)
return address
# Commands
if args.storage:
if not args.address:
exit_with_error(
args.outform,
"To read storage, provide the address of a deployed contract with the -a option.",
)
storage = mythril.get_state_variable_from_storage( def execute_command(
address=address, mythril: Mythril,
params=[a.strip() for a in args.storage.strip().split(",")], address: str,
parser: argparse.ArgumentParser,
args: argparse.Namespace,
):
if args.storage:
if not args.address:
exit_with_error(
args.outform,
"To read storage, provide the address of a deployed contract with the -a option.",
) )
print(storage)
elif args.disassemble:
# or mythril.disassemble(mythril.contracts[0])
if mythril.contracts[0].code: storage = mythril.get_state_variable_from_storage(
print("Runtime Disassembly: \n" + mythril.contracts[0].get_easm()) address=address, params=[a.strip() for a in args.storage.strip().split(",")]
if mythril.contracts[0].creation_code: )
print("Disassembly: \n" + mythril.contracts[0].get_creation_easm()) print(storage)
elif args.graph or args.fire_lasers: elif args.disassemble:
if not mythril.contracts: # or mythril.disassemble(mythril.contracts[0])
exit_with_error(
args.outform, "input files do not contain any valid contracts"
)
if args.graph: if mythril.contracts[0].code:
html = mythril.graph_html( print("Runtime Disassembly: \n" + mythril.contracts[0].get_easm())
strategy=args.strategy, if mythril.contracts[0].creation_code:
contract=mythril.contracts[0], print("Disassembly: \n" + mythril.contracts[0].get_creation_easm())
address=address,
enable_physics=args.enable_physics,
phrackify=args.phrack,
max_depth=args.max_depth,
execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout,
enable_iprof=args.enable_iprof,
)
try: elif args.graph or args.fire_lasers:
with open(args.graph, "w") as f: if not mythril.contracts:
f.write(html) exit_with_error(
except Exception as e: args.outform, "input files do not contain any valid contracts"
exit_with_error(args.outform, "Error saving graph: " + str(e)) )
else:
try:
report = mythril.fire_lasers(
strategy=args.strategy,
address=address,
modules=[m.strip() for m in args.modules.strip().split(",")]
if args.modules
else [],
verbose_report=args.verbose_report,
max_depth=args.max_depth,
execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout,
transaction_count=args.transaction_count,
enable_iprof=args.enable_iprof,
)
outputs = {
"json": report.as_json(),
"jsonv2": report.as_swc_standard_format(),
"text": report.as_text(),
"markdown": report.as_markdown(),
}
print(outputs[args.outform])
except ModuleNotFoundError as e:
exit_with_error(
args.outform, "Error loading analyis modules: " + format(e)
)
elif args.statespace_json:
if not mythril.contracts:
exit_with_error(
args.outform, "input files do not contain any valid contracts"
)
statespace = mythril.dump_statespace( if args.graph:
html = mythril.graph_html(
strategy=args.strategy, strategy=args.strategy,
contract=mythril.contracts[0], contract=mythril.contracts[0],
address=address, address=address,
enable_physics=args.enable_physics,
phrackify=args.phrack,
max_depth=args.max_depth, max_depth=args.max_depth,
execution_timeout=args.execution_timeout, execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout, create_timeout=args.create_timeout,
@ -476,16 +432,107 @@ def main():
) )
try: try:
with open(args.statespace_json, "w") as f: with open(args.graph, "w") as f:
json.dump(statespace, f) f.write(html)
except Exception as e: except Exception as e:
exit_with_error(args.outform, "Error saving json: " + str(e)) exit_with_error(args.outform, "Error saving graph: " + str(e))
else: else:
parser.print_help() try:
report = mythril.fire_lasers(
strategy=args.strategy,
address=address,
modules=[m.strip() for m in args.modules.strip().split(",")]
if args.modules
else [],
verbose_report=args.verbose_report,
max_depth=args.max_depth,
execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout,
transaction_count=args.transaction_count,
enable_iprof=args.enable_iprof,
)
outputs = {
"json": report.as_json(),
"jsonv2": report.as_swc_standard_format(),
"text": report.as_text(),
"markdown": report.as_markdown(),
}
print(outputs[args.outform])
except ModuleNotFoundError as e:
exit_with_error(
args.outform, "Error loading analyis modules: " + format(e)
)
elif args.statespace_json:
if not mythril.contracts:
exit_with_error(
args.outform, "input files do not contain any valid contracts"
)
statespace = mythril.dump_statespace(
strategy=args.strategy,
contract=mythril.contracts[0],
address=address,
max_depth=args.max_depth,
execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout,
enable_iprof=args.enable_iprof,
)
try:
with open(args.statespace_json, "w") as f:
json.dump(statespace, f)
except Exception as e:
exit_with_error(args.outform, "Error saving json: " + str(e))
else:
parser.print_help()
def parse_args(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
"""
Parses the arguments
:param parser: The parser
:param args: The args
"""
if args.epic:
path = os.path.dirname(os.path.realpath(__file__))
sys.argv.remove("--epic")
os.system(" ".join(sys.argv) + " | python3 " + path + "/epic.py")
sys.exit()
if args.version:
if args.outform == "json":
print(json.dumps({"version_str": VERSION}))
else:
print("Mythril version {}".format(VERSION))
sys.exit()
# Parse cmdline args
validate_args(parser, args)
try:
quick_commands(args)
mythril = set_config(args)
leveldb_search(mythril, args)
if args.truffle:
try:
mythril.analyze_truffle_project(args)
except FileNotFoundError:
print(
"Build directory not found. Make sure that you start the analysis from the project root, and that 'truffle compile' has executed successfully."
)
sys.exit()
address = get_code(mythril, args)
execute_command(mythril=mythril, address=address, parser=parser, args=args)
except CriticalError as ce: except CriticalError as ce:
exit_with_error(args.outform, str(ce)) exit_with_error(args.outform, str(ce))
except Exception:
exit_with_error(args.outform, traceback.format_exc())
if __name__ == "__main__": if __name__ == "__main__":

@ -62,6 +62,9 @@ OPCODE_GAS = {
"XOR": (3, 3), "XOR": (3, 3),
"NOT": (3, 3), "NOT": (3, 3),
"BYTE": (3, 3), "BYTE": (3, 3),
"SHL": (3, 3),
"SHR": (3, 3),
"SAR": (3, 3),
"SHA3": ( "SHA3": (
30, 30,
30 + 6 * 8, 30 + 6 * 8,
@ -80,6 +83,7 @@ OPCODE_GAS = {
"GASPRICE": (2, 2), "GASPRICE": (2, 2),
"EXTCODESIZE": (700, 700), "EXTCODESIZE": (700, 700),
"EXTCODECOPY": (700, 700 + 3 * 768), # https://ethereum.stackexchange.com/a/47556 "EXTCODECOPY": (700, 700 + 3 * 768), # https://ethereum.stackexchange.com/a/47556
"EXTCODEHASH": (400, 400),
"RETURNDATASIZE": (2, 2), "RETURNDATASIZE": (2, 2),
"RETURNDATACOPY": (3, 3), "RETURNDATACOPY": (3, 3),
"BLOCKHASH": (20, 20), "BLOCKHASH": (20, 20),
@ -176,6 +180,10 @@ OPCODE_GAS = {
"LOG3": (4 * 375, 4 * 375 + 8 * 32), "LOG3": (4 * 375, 4 * 375 + 8 * 32),
"LOG4": (5 * 375, 5 * 375 + 8 * 32), "LOG4": (5 * 375, 5 * 375 + 8 * 32),
"CREATE": (32000, 32000), "CREATE": (32000, 32000),
"CREATE2": (
32000,
32000,
), # TODO: The gas value is dynamic, to be done while implementing create2
"CALL": (700, 700 + 9000 + 25000), "CALL": (700, 700 + 9000 + 25000),
"NATIVE_COST": calculate_native_gas, "NATIVE_COST": calculate_native_gas,
"CALLCODE": (700, 700 + 9000 + 25000), "CALLCODE": (700, 700 + 9000 + 25000),

@ -26,6 +26,7 @@ from mythril.laser.smt import (
Bool, Bool,
Or, Or,
Not, Not,
LShR,
) )
from mythril.laser.smt import symbol_factory from mythril.laser.smt import symbol_factory
@ -464,6 +465,33 @@ class Instruction:
global_state.mstate.stack.append(0 if s1 == 0 else URem(s0, s1)) global_state.mstate.stack.append(0 if s1 == 0 else URem(s0, s1))
return [global_state] return [global_state]
@StateTransition()
def shl_(self, global_state: GlobalState) -> List[GlobalState]:
shift, value = (
util.pop_bitvec(global_state.mstate),
util.pop_bitvec(global_state.mstate),
)
global_state.mstate.stack.append(value << shift)
return [global_state]
@StateTransition()
def shr_(self, global_state: GlobalState) -> List[GlobalState]:
shift, value = (
util.pop_bitvec(global_state.mstate),
util.pop_bitvec(global_state.mstate),
)
global_state.mstate.stack.append(LShR(value, shift))
return [global_state]
@StateTransition()
def sar_(self, global_state: GlobalState) -> List[GlobalState]:
shift, value = (
util.pop_bitvec(global_state.mstate),
util.pop_bitvec(global_state.mstate),
)
global_state.mstate.stack.append(value >> shift)
return [global_state]
@StateTransition() @StateTransition()
def smod_(self, global_state: GlobalState) -> List[GlobalState]: def smod_(self, global_state: GlobalState) -> List[GlobalState]:
""" """
@ -1082,6 +1110,20 @@ class Instruction:
return [global_state] return [global_state]
@StateTransition
def extcodehash_(self, global_state: GlobalState) -> List[GlobalState]:
"""
:param global_state:
:return: List of global states possible, list of size 1 in this case
"""
# TODO: To be implemented
address = global_state.mstate.stack.pop()
global_state.mstate.stack.append(
global_state.new_bitvec("extcodehash_{}".format(str(address)), 256)
)
return [global_state]
@StateTransition() @StateTransition()
def extcodecopy_(self, global_state: GlobalState) -> List[GlobalState]: def extcodecopy_(self, global_state: GlobalState) -> List[GlobalState]:
""" """
@ -1671,6 +1713,25 @@ class Instruction:
state.stack.append(0) state.stack.append(0)
return [global_state] return [global_state]
@StateTransition()
def create2_(self, global_state: GlobalState) -> List[GlobalState]:
"""
:param global_state:
:return:
"""
# TODO: implement me
state = global_state.mstate
endowment, memory_start, memory_length, salt = (
state.stack.pop(),
state.stack.pop(),
state.stack.pop(),
state.stack.pop(),
)
# Not supported
state.stack.append(0)
return [global_state]
@StateTransition() @StateTransition()
def return_(self, global_state: GlobalState): def return_(self, global_state: GlobalState):
""" """

@ -29,6 +29,11 @@ class Memory:
""" """
return len(self._memory) return len(self._memory)
def __copy__(self):
copy = Memory()
copy._memory = self._memory[:]
return copy
def extend(self, size): def extend(self, size):
""" """

@ -449,5 +449,6 @@ class TaintRunner:
"MSIZE": (0, 1), "MSIZE": (0, 1),
"GAS": (0, 1), "GAS": (0, 1),
"CREATE": (3, 1), "CREATE": (3, 1),
"CREATE2": (4, 1),
"RETURN": (2, 0), "RETURN": (2, 0),
} }

@ -13,6 +13,7 @@ from mythril.laser.smt.bitvec import (
BVAddNoOverflow, BVAddNoOverflow,
BVMulNoOverflow, BVMulNoOverflow,
BVSubNoUnderflow, BVSubNoUnderflow,
LShR,
) )
from mythril.laser.smt.bitvecfunc import BitVecFunc from mythril.laser.smt.bitvecfunc import BitVecFunc
from mythril.laser.smt.expression import Expression, simplify from mythril.laser.smt.expression import Expression, simplify

@ -1,7 +1,7 @@
"""This module provides classes for an SMT abstraction of bit vectors.""" """This module provides classes for an SMT abstraction of bit vectors."""
from typing import Union, overload, List, cast, Any, Optional, Callable from typing import Union, overload, List, cast, Any, Optional, Callable
from operator import lshift, rshift
import z3 import z3
from mythril.laser.smt.bool import Bool, And, Or from mythril.laser.smt.bool import Bool, And, Or
@ -211,6 +211,38 @@ class BitVec(Expression[z3.BitVecRef]):
# MYPY: fix complaints due to z3 overriding __eq__ # MYPY: fix complaints due to z3 overriding __eq__
return Bool(cast(z3.BoolRef, self.raw != other.raw), annotations=union) return Bool(cast(z3.BoolRef, self.raw != other.raw), annotations=union)
def _handle_shift(self, other: Union[int, "BitVec"], operator: Callable) -> "BitVec":
"""
Handles shift
:param other: The other BitVector
:param operator: The shift operator
:return: the resulting output
"""
if isinstance(other, BitVecFunc):
return operator(other, self)
if not isinstance(other, BitVec):
return BitVec(
operator(self.raw, other), annotations=self.annotations
)
union = self.annotations + other.annotations
return BitVec(operator(self.raw, other.raw), annotations=union)
def __lshift__(self, other: Union[int, "BitVec"]) -> "BitVec":
"""
:param other:
:return:
"""
return self._handle_shift(other, lshift)
def __rshift__(self, other: Union[int, "BitVec"]) -> "BitVec":
"""
:param other:
:return:
"""
return self._handle_shift(other, rshift)
def _comparison_helper( def _comparison_helper(
a: BitVec, b: BitVec, operation: Callable, default_value: bool, inputs_equal: bool a: BitVec, b: BitVec, operation: Callable, default_value: bool, inputs_equal: bool
@ -254,6 +286,10 @@ def _arithmetic_helper(a: BitVec, b: BitVec, operation: Callable) -> BitVec:
return BitVec(raw, annotations=union) return BitVec(raw, annotations=union)
def LShR(a: BitVec, b: BitVec):
return _arithmetic_helper(a, b, z3.LShR)
def If(a: Union[Bool, bool], b: Union[BitVec, int], c: Union[BitVec, int]) -> BitVec: def If(a: Union[Bool, bool], b: Union[BitVec, int], c: Union[BitVec, int]) -> BitVec:
"""Create an if-then-else expression. """Create an if-then-else expression.

@ -207,3 +207,19 @@ class BitVecFunc(BitVec):
return _comparison_helper( return _comparison_helper(
self, other, operator.eq, default_value=True, inputs_equal=False self, other, operator.eq, default_value=True, inputs_equal=False
) )
def __lshift__(self, other: Union[int, "BitVec"]) -> "BitVec":
"""
Left shift operation
:param other: The int or BitVec to shift on
:return The resulting left shifted output
"""
return _arithmetic_helper(self, other, operator.lshift)
def __rshift__(self, other: Union[int, "BitVec"]) -> "BitVec":
"""
Right shift operation
:param other: The int or BitVec to shift on
:return The resulting right shifted output:
"""
return _arithmetic_helper(self, other, operator.rshift)

@ -570,6 +570,7 @@ class Mythril(object):
""" """
all_issues = [] all_issues = []
SolverStatistics().enabled = True SolverStatistics().enabled = True
exceptions = []
for contract in contracts or self.contracts: for contract in contracts or self.contracts:
StartTime() # Reinitialize start time for new contracts StartTime() # Reinitialize start time for new contracts
try: try:
@ -600,7 +601,7 @@ class Mythril(object):
+ traceback.format_exc() + traceback.format_exc()
) )
issues = retrieve_callback_issues(modules) issues = retrieve_callback_issues(modules)
exceptions.append(traceback.format_exc())
for issue in issues: for issue in issues:
issue.add_code_info(contract) issue.add_code_info(contract)
@ -610,7 +611,7 @@ class Mythril(object):
source_data = Source() source_data = Source()
source_data.get_source_from_contracts_list(self.contracts) source_data.get_source_from_contracts_list(self.contracts)
# Finally, output the results # Finally, output the results
report = Report(verbose_report, source_data) report = Report(verbose_report, source_data, exceptions=exceptions)
for issue in all_issues: for issue in all_issues:
report.append_issue(issue) report.append_issue(issue)

@ -161,11 +161,14 @@ class SolidityContract(EVMContract):
if len(mapping) > 2 and len(mapping[2]) > 0: if len(mapping) > 2 and len(mapping[2]) > 0:
idx = int(mapping[2]) idx = int(mapping[2])
lineno = ( if idx == -1:
self.solidity_files[idx] lineno = None
.data.encode("utf-8")[0:offset] else:
.count("\n".encode("utf-8")) lineno = (
+ 1 self.solidity_files[idx]
) .data.encode("utf-8")[0:offset]
.count("\n".encode("utf-8"))
+ 1
)
prev_item = item prev_item = item
mappings.append(SourceMapping(idx, offset, length, lineno, item)) mappings.append(SourceMapping(idx, offset, length, lineno, item))

@ -0,0 +1,94 @@
# This pyethereum opcodes file with added opcodes
from typing import Dict, Tuple
opcodes = {
0x00: ("STOP", 0, 0, 0),
0x01: ("ADD", 2, 1, 3),
0x02: ("MUL", 2, 1, 5),
0x03: ("SUB", 2, 1, 3),
0x04: ("DIV", 2, 1, 5),
0x05: ("SDIV", 2, 1, 5),
0x06: ("MOD", 2, 1, 5),
0x07: ("SMOD", 2, 1, 5),
0x08: ("ADDMOD", 3, 1, 8),
0x09: ("MULMOD", 3, 1, 8),
0x0A: ("EXP", 2, 1, 10),
0x0B: ("SIGNEXTEND", 2, 1, 5),
0x10: ("LT", 2, 1, 3),
0x11: ("GT", 2, 1, 3),
0x12: ("SLT", 2, 1, 3),
0x13: ("SGT", 2, 1, 3),
0x14: ("EQ", 2, 1, 3),
0x15: ("ISZERO", 1, 1, 3),
0x16: ("AND", 2, 1, 3),
0x17: ("OR", 2, 1, 3),
0x18: ("XOR", 2, 1, 3),
0x19: ("NOT", 1, 1, 3),
0x1A: ("BYTE", 2, 1, 3),
0x1B: ("SHL", 2, 1, 3),
0x1C: ("SHR", 2, 1, 3),
0x1D: ("SAR", 2, 1, 3),
0x20: ("SHA3", 2, 1, 30),
0x30: ("ADDRESS", 0, 1, 2),
0x31: ("BALANCE", 1, 1, 20), # now 400
0x32: ("ORIGIN", 0, 1, 2),
0x33: ("CALLER", 0, 1, 2),
0x34: ("CALLVALUE", 0, 1, 2),
0x35: ("CALLDATALOAD", 1, 1, 3),
0x36: ("CALLDATASIZE", 0, 1, 2),
0x37: ("CALLDATACOPY", 3, 0, 3),
0x38: ("CODESIZE", 0, 1, 2),
0x39: ("CODECOPY", 3, 0, 3),
0x3A: ("GASPRICE", 0, 1, 2),
0x3B: ("EXTCODESIZE", 1, 1, 20), # now 700
0x3C: ("EXTCODECOPY", 4, 0, 20), # now 700
0x3D: ("RETURNDATASIZE", 0, 1, 2),
0x3E: ("RETURNDATACOPY", 3, 0, 3),
0x3F: ("EXTCODEHASH", 3, 0, 3),
0x40: ("BLOCKHASH", 1, 1, 20),
0x41: ("COINBASE", 0, 1, 2),
0x42: ("TIMESTAMP", 0, 1, 2),
0x43: ("NUMBER", 0, 1, 2),
0x44: ("DIFFICULTY", 0, 1, 2),
0x45: ("GASLIMIT", 0, 1, 2),
0x50: ("POP", 1, 0, 2),
0x51: ("MLOAD", 1, 1, 3),
0x52: ("MSTORE", 2, 0, 3),
0x53: ("MSTORE8", 2, 0, 3),
0x54: ("SLOAD", 1, 1, 50), # 200 now
0x55: ("SSTORE", 2, 0, 0),
0x56: ("JUMP", 1, 0, 8),
0x57: ("JUMPI", 2, 0, 10),
0x58: ("PC", 0, 1, 2),
0x59: ("MSIZE", 0, 1, 2),
0x5A: ("GAS", 0, 1, 2),
0x5B: ("JUMPDEST", 0, 0, 1),
0xA0: ("LOG0", 2, 0, 375),
0xA1: ("LOG1", 3, 0, 750),
0xA2: ("LOG2", 4, 0, 1125),
0xA3: ("LOG3", 5, 0, 1500),
0xA4: ("LOG4", 6, 0, 1875),
0xF0: ("CREATE", 3, 1, 32000),
0xF1: ("CALL", 7, 1, 40), # 700 now
0xF2: ("CALLCODE", 7, 1, 40), # 700 now
0xF3: ("RETURN", 2, 0, 0),
0xF4: ("DELEGATECALL", 6, 1, 40), # 700 now
0xF5: ("CREATE2", 3, 1, 32000),
0xFA: ("STATICCALL", 6, 1, 40),
0xFD: ("REVERT", 2, 0, 0),
0xFF: ("SUICIDE", 1, 0, 0), # 5000 now
} # type: Dict[int, Tuple[str, int, int, int]]
opcodesMetropolis = {0x3D, 0x3E, 0xFA, 0xFD}
for i in range(1, 33):
opcodes[0x5F + i] = ("PUSH" + str(i), 0, 1, 3)
for i in range(1, 17):
opcodes[0x7F + i] = ("DUP" + str(i), i, i + 1, 3)
opcodes[0x8F + i] = ("SWAP" + str(i), i + 1, i + 1, 3)
reverse_opcodes = {}
for o in opcodes:
vars()[opcodes[o][0]] = opcodes[o]
reverse_opcodes[opcodes[o][0]] = o

@ -5,6 +5,7 @@ import logging
import os import os
import re import re
import sys import sys
import warnings
from pathlib import PurePath from pathlib import PurePath
from ethereum.utils import sha3 from ethereum.utils import sha3
@ -20,12 +21,24 @@ from mythril.solidity.soliditycontract import SourceMapping
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def format_Warning(message, category, filename, lineno, line=""):
return "{}: {}\n\n".format(str(filename), str(message))
warnings.formatwarning = format_Warning
def analyze_truffle_project(sigs, args): def analyze_truffle_project(sigs, args):
""" """
:param sigs: :param sigs:
:param args: :param args:
""" """
warnings.warn(
"The option --truffle is being deprecated, Please use the truffle-security plugin, https://github.com/ConsenSys/truffle-security",
FutureWarning,
)
project_root = os.getcwd() project_root = os.getcwd()
build_dir = os.path.join(project_root, "build", "contracts") build_dir = os.path.join(project_root, "build", "contracts")
@ -181,7 +194,10 @@ def get_mappings(source, deployed_source_map):
if len(mapping) > 2 and len(mapping[2]) > 0: if len(mapping) > 2 and len(mapping[2]) > 0:
idx = int(mapping[2]) idx = int(mapping[2])
lineno = source.encode("utf-8")[0:offset].count("\n".encode("utf-8")) + 1 if idx == -1:
lineno = None
else:
lineno = source.encode("utf-8")[0:offset].count("\n".encode("utf-8")) + 1
prev_item = item prev_item = item
mappings.append(SourceMapping(idx, offset, length, lineno, item)) mappings.append(SourceMapping(idx, offset, length, lineno, item))

@ -4,4 +4,4 @@ This file is suitable for sourcing inside POSIX shell, e.g. bash as well
as for importing into Python. as for importing into Python.
""" """
VERSION = "v0.20.0" # NOQA VERSION = "v0.20.1" # NOQA

@ -212,7 +212,7 @@ contract WalletLibrary is WalletEvents {
} }
// throw unless the contract is not yet initialized. // throw unless the contract is not yet initialized.
modifier only_uninitialized { require(m_numOwners > 0); _; } modifier only_uninitialized { require(m_numOwners == 0); _; }
// constructor - just pass on the owner array to the multiowned and // constructor - just pass on the owner array to the multiowned and
// the limit to daylimit // the limit to daylimit

@ -34,7 +34,7 @@ contract Rubixi {
//Fee functions for creator //Fee functions for creator
function collectAllFees() public onlyowner { function collectAllFees() public onlyowner {
require(collectedFees == 0); require(collectedFees > 0);
creator.transfer(collectedFees); creator.transfer(collectedFees);
collectedFees = 0; collectedFees = 0;
} }
@ -43,14 +43,14 @@ contract Rubixi {
_amt *= 1 ether; _amt *= 1 ether;
if (_amt > collectedFees) collectAllFees(); if (_amt > collectedFees) collectAllFees();
require(collectedFees == 0); require(collectedFees > 0);
creator.transfer(_amt); creator.transfer(_amt);
collectedFees -= _amt; collectedFees -= _amt;
} }
function collectPercentOfFees(uint _pcent) public onlyowner { function collectPercentOfFees(uint _pcent) public onlyowner {
require(collectedFees == 0 || _pcent > 100); require(collectedFees > 0 && _pcent <= 100);
uint feesToCollect = collectedFees / 100 * _pcent; uint feesToCollect = collectedFees / 100 * _pcent;
creator.transfer(feesToCollect); creator.transfer(feesToCollect);
@ -63,12 +63,12 @@ contract Rubixi {
} }
function changeMultiplier(uint _mult) public onlyowner { function changeMultiplier(uint _mult) public onlyowner {
require(_mult > 300 || _mult < 120); require(_mult <= 300 && _mult >= 120);
pyramidMultiplier = _mult; pyramidMultiplier = _mult;
} }
function changeFeePercentage(uint _fee) public onlyowner { function changeFeePercentage(uint _fee) public onlyowner {
require(_fee > 10); require(_fee <= 10);
feePercent = _fee; feePercent = _fee;
} }

@ -0,0 +1,148 @@
import pytest
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.smt import symbol_factory, simplify
def get_state():
active_account = Account("0x0", code=Disassembly("60606040"))
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
)
return state
BVV = symbol_factory.BitVecVal
BV = symbol_factory.BitVecSym
test_data = (
([BVV(-1, 256), BVV(1, 256)], BVV(-1, 256)),
([BVV(23, 256), BVV(257, 256)], BVV(0, 256)),
([BVV(23, 256), BVV(30, 256)], BVV(23 >> 30, 256)),
([BVV(-10, 256), BVV(10, 256)], BVV(-1, 256)),
([BV("a", 256), BV("b", 256)], BV("a", 256) >> BV("b", 256)),
)
@pytest.mark.parametrize("inputs,output", test_data)
def test_sar(inputs, output):
# Arrange
state = get_state()
state.mstate.stack = inputs
instruction = Instruction("sar", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == output
@pytest.mark.parametrize(
# Test cases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right
"val1, val2, expected ",
(
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x00",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x01",
"0xc000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0xff",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x0100",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x0101",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x00",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xff",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0100",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x4000000000000000000000000000000000000000000000000000000000000000",
"0xfe",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xf8",
"0x000000000000000000000000000000000000000000000000000000000000007f",
),
(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xfe",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xff",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0100",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
),
)
def test_concrete_sar(val1, val2, expected):
# Arrange
state = get_state()
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)]
expected = BVV(int(expected, 16), 256)
instruction = Instruction("sar", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == expected

@ -0,0 +1,123 @@
import pytest
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.smt import symbol_factory, simplify
def get_state():
active_account = Account("0x0", code=Disassembly("60606040"))
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
)
return state
BVV = symbol_factory.BitVecVal
BV = symbol_factory.BitVecSym
test_data = (
([BVV(2, 256), BVV(2, 256)], BVV(8, 256)),
([BVV(23, 256), BVV(257, 256)], BVV(0, 256)),
([BVV(23, 256), BVV(30, 256)], BVV(23 * (1 << 30), 256)),
([BV("a", 256), BVV(270, 256)], 0),
([BV("a", 256), BV("b", 256)], BV("a", 256) << BV("b", 256)),
)
@pytest.mark.parametrize("inputs,output,", test_data)
def test_shl(inputs, output):
# Arrange
state = get_state()
state.mstate.stack = inputs
instruction = Instruction("shl", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == output
@pytest.mark.parametrize(
# Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
"val1, val2, expected",
(
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x00",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000002",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0xff",
"0x8000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0100",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0101",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x00",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xff",
"0x8000000000000000000000000000000000000000000000000000000000000000",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0100",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
),
),
)
def test_concrete_shl(val1, val2, expected):
# Arrange
state = get_state()
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)]
expected = BVV(int(expected, 16), 256)
instruction = Instruction("shl", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == expected

@ -0,0 +1,125 @@
import pytest
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.smt import symbol_factory, simplify, LShR
def get_state():
active_account = Account("0x0", code=Disassembly("60606040"))
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000))
state.transaction_stack.append(
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
)
return state
BVV = symbol_factory.BitVecVal
BV = symbol_factory.BitVecSym
test_data = (
([BVV(33, 256), BVV(4, 256)], BVV(2, 256)),
([BVV(1 << 100, 256), BVV(257, 256)], BVV(0, 256)),
([BVV(23233, 256), BVV(10, 256)], BVV(23233 // (1 << 10), 256)),
([BV("a", 256), BVV(270, 256)], 0),
(
[BV("a", 256), BV("b", 256)],
LShR(BV("a", 256), BV("b", 256)),
), # Current approximate specs
)
@pytest.mark.parametrize("inputs,output,", test_data)
def test_shr(inputs, output):
# Arrange
state = get_state()
state.mstate.stack = inputs
instruction = Instruction("shr", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == output
@pytest.mark.parametrize(
# Cases: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right
"val1, val2, expected",
(
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x00",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x01",
"0x4000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0xff",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x0100",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x8000000000000000000000000000000000000000000000000000000000000000",
"0x0101",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x00",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01",
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0xff",
"0x0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x0100",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x01",
"0x0000000000000000000000000000000000000000000000000000000000000000",
),
),
)
def test_concrete_shr(val1, val2, expected):
state = get_state()
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)]
expected = BVV(int(expected, 16), 256)
instruction = Instruction("shr", dynamic_loader=None)
# Act
new_state = instruction.evaluate(state)[0]
# Assert
assert simplify(new_state.mstate.stack[-1]) == expected

@ -1,150 +1 @@
[ [{"issues": [{"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "661:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "779:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "858:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "A call to a user-supplied address is executed.", "tail": "The 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."}, "extra": {}, "locations": [{"sourceMap": "912:1:0"}], "severity": "Medium", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "661:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "779:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "858:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "912:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x7cbb77986c6b1bf6e945cd3fba06d3ea3d28cfc49cdfdc9571ec30703ac5862f"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "The contract executes an external message call.",
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."
},
"extra": {
},
"locations": [
{
"sourceMap": "661:1:0"
}
],
"severity": "Low",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "The contract executes an external message call.",
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."
},
"extra": {
},
"locations": [
{
"sourceMap": "779:1:0"
}
],
"severity": "Low",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "The contract executes an external message call.",
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."
},
"extra": {
},
"locations": [
{
"sourceMap": "858:1:0"
}
],
"severity": "Low",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "A call to a user-supplied address is executed.",
"tail": "The 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."
},
"extra": {
},
"locations": [
{
"sourceMap": "912:1:0"
}
],
"severity": "Medium",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {
},
"locations": [
{
"sourceMap": "661:1:0"
}
],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
},
{
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {
},
"locations": [
{
"sourceMap": "779:1:0"
}
],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
},
{
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {
},
"locations": [
{
"sourceMap": "858:1:0"
}
],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
},
{
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {
},
"locations": [
{
"sourceMap": "912:1:0"
}
],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
}
],
"meta": {
},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x7cbb77986c6b1bf6e945cd3fba06d3ea3d28cfc49cdfdc9571ec30703ac5862f"
],
"sourceType": "raw-bytecode"
}
]

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

@ -1,72 +1 @@
[ [{"issues": [{"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "446:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "484:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "506:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "531:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x4a773a86bc6fb269f88bf09bb3094de29b6073cf13b1760e9d01d957f50a9dfd"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "A reachable exception has been detected.",
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."
},
"extra": {},
"locations": [
{
"sourceMap": "446:1:0"
}
],
"severity": "Low",
"swcID": "SWC-110",
"swcTitle": "Assert Violation"
},
{
"description": {
"head": "A reachable exception has been detected.",
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."
},
"extra": {},
"locations": [
{
"sourceMap": "484:1:0"
}
],
"severity": "Low",
"swcID": "SWC-110",
"swcTitle": "Assert Violation"
},
{
"description": {
"head": "A reachable exception has been detected.",
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."
},
"extra": {},
"locations": [
{
"sourceMap": "506:1:0"
}
],
"severity": "Low",
"swcID": "SWC-110",
"swcTitle": "Assert Violation"
},
{
"description": {
"head": "A reachable exception has been detected.",
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."
},
"extra": {},
"locations": [
{
"sourceMap": "531:1:0"
}
],
"severity": "Low",
"swcID": "SWC-110",
"swcTitle": "Assert Violation"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x4a773a86bc6fb269f88bf09bb3094de29b6073cf13b1760e9d01d957f50a9dfd"
],
"sourceType": "raw-bytecode"
}
]

@ -33,8 +33,8 @@
"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": "_function_0x9b58bc26", "function": "_function_0x9b58bc26",
"max_gas_used": 35922, "max_gas_used": 35928,
"min_gas_used": 1170, "min_gas_used": 1176,
"severity": "Low", "severity": "Low",
"sourceMap": null, "sourceMap": null,
"swc-id": "104", "swc-id": "104",
@ -46,8 +46,8 @@
"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": "_function_0xeea4c864", "function": "_function_0xeea4c864",
"max_gas_used": 1223, "max_gas_used": 1229,
"min_gas_used": 471, "min_gas_used": 477,
"severity": "Medium", "severity": "Medium",
"sourceMap": null, "sourceMap": null,
"swc-id": "107", "swc-id": "107",
@ -59,8 +59,8 @@
"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": "_function_0xeea4c864", "function": "_function_0xeea4c864",
"max_gas_used": 35947, "max_gas_used": 35953,
"min_gas_used": 1195, "min_gas_used": 1201,
"severity": "Low", "severity": "Low",
"sourceMap": null, "sourceMap": null,
"swc-id": "104", "swc-id": "104",

@ -1,67 +1 @@
[{ [{"issues": [{"description": {"head": "Use of callcode is deprecated.", "tail": "The callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead."}, "extra": {}, "locations": [{"sourceMap": "618:1:0"}], "severity": "Medium", "swcID": "SWC-111", "swcTitle": "Use of Deprecated Solidity Functions"}, {"description": {"head": "A call to a user-supplied address is executed.", "tail": "The 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."}, "extra": {}, "locations": [{"sourceMap": "1038:1:0"}], "severity": "Medium", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "618:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "849:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "1038:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x6daec61d05d8f1210661e7e7d1ed6d72bd6ade639398fac1e867aff50abfc1c1"], "sourceType": "raw-bytecode"}]
"issues": [{
"description": {
"head": "Use of callcode is deprecated.",
"tail": "The callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead."
},
"extra": {},
"locations": [{
"sourceMap": "618:1:0"
}],
"severity": "Medium",
"swcID": "SWC-111",
"swcTitle": "Use of Deprecated Solidity Functions"
}, {
"description": {
"head": "A call to a user-supplied address is executed.",
"tail": "The 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."
},
"extra": {},
"locations": [{
"sourceMap": "1038:1:0"
}],
"severity": "Medium",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
}, {
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {},
"locations": [{
"sourceMap": "618:1:0"
}],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
}, {
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {},
"locations": [{
"sourceMap": "849:1:0"
}],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
}, {
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {},
"locations": [{
"sourceMap": "1038:1:0"
}],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
}],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": ["0x6daec61d05d8f1210661e7e7d1ed6d72bd6ade639398fac1e867aff50abfc1c1"],
"sourceType": "raw-bytecode"
}]

@ -32,7 +32,7 @@ The callcode method executes code of another contract in the context of the call
- Contract: Unknown - Contract: Unknown
- Function name: `_function_0x9b58bc26` - Function name: `_function_0x9b58bc26`
- PC address: 849 - PC address: 849
- Estimated Gas Usage: 1170 - 35922 - Estimated Gas Usage: 1176 - 35928
### Description ### Description
@ -45,7 +45,7 @@ External calls return a boolean value. If the callee contract halts with an exce
- Contract: Unknown - Contract: Unknown
- Function name: `_function_0xeea4c864` - Function name: `_function_0xeea4c864`
- PC address: 1038 - PC address: 1038
- Estimated Gas Usage: 471 - 1223 - Estimated Gas Usage: 477 - 1229
### Description ### Description
@ -58,7 +58,7 @@ The callee address of an external message call can be set by the caller. Note th
- Contract: Unknown - Contract: Unknown
- Function name: `_function_0xeea4c864` - Function name: `_function_0xeea4c864`
- PC address: 1038 - PC address: 1038
- Estimated Gas Usage: 1195 - 35947 - Estimated Gas Usage: 1201 - 35953
### Description ### Description

@ -26,7 +26,7 @@ Severity: Low
Contract: Unknown Contract: Unknown
Function name: _function_0x9b58bc26 Function name: _function_0x9b58bc26
PC address: 849 PC address: 849
Estimated Gas Usage: 1170 - 35922 Estimated Gas Usage: 1176 - 35928
The return value of a message call is not checked. The return value of a message call is not checked.
External 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. External 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.
-------------------- --------------------
@ -37,7 +37,7 @@ Severity: Medium
Contract: Unknown Contract: Unknown
Function name: _function_0xeea4c864 Function name: _function_0xeea4c864
PC address: 1038 PC address: 1038
Estimated Gas Usage: 471 - 1223 Estimated Gas Usage: 477 - 1229
A call to a user-supplied address is executed. A call to a user-supplied address is executed.
The 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. The 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.
-------------------- --------------------
@ -48,7 +48,7 @@ Severity: Low
Contract: Unknown Contract: Unknown
Function name: _function_0xeea4c864 Function name: _function_0xeea4c864
PC address: 1038 PC address: 1038
Estimated Gas Usage: 1195 - 35947 Estimated Gas Usage: 1201 - 35953
The return value of a message call is not checked. The return value of a message call is not checked.
External 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. External 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.
-------------------- --------------------

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

@ -1,27 +1 @@
[ [{"issues": [{"description": {"head": "Anyone can withdraw ETH from the contract account.", "tail": "Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability."}, "extra": {}, "locations": [{"sourceMap": "142:1:0"}], "severity": "High", "swcID": "SWC-105", "swcTitle": "Unprotected Ether Withdrawal"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xbc9c3d9db56d20cf4ca3b6fd88ff9215cf728a092cca1ed8edb83272b933ff5b"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "Anyone can withdraw ETH from the contract account.",
"tail": "Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability."
},
"extra": {},
"locations": [
{
"sourceMap": "142:1:0"
}
],
"severity": "High",
"swcID": "SWC-105",
"swcTitle": "Unprotected Ether Withdrawal"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0xbc9c3d9db56d20cf4ca3b6fd88ff9215cf728a092cca1ed8edb83272b933ff5b"
],
"sourceType": "raw-bytecode"
}
]

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

@ -1,27 +1 @@
[ [{"issues": [{"description": {"head": "Use of tx.origin is deprecated.", "tail": "The smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin"}, "extra": {}, "locations": [{"sourceMap": "317:1:0"}], "severity": "Medium", "swcID": "SWC-111", "swcTitle": "Use of Deprecated Solidity Functions"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x25b20ef097dfc0aa56a932c4e09f06ee02a69c005767df86877f48c6c2412f03"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "Use of tx.origin is deprecated.",
"tail": "The smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin"
},
"extra": {},
"locations": [
{
"sourceMap": "317:1:0"
}
],
"severity": "Medium",
"swcID": "SWC-111",
"swcTitle": "Use of Deprecated Solidity Functions"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0x25b20ef097dfc0aa56a932c4e09f06ee02a69c005767df86877f48c6c2412f03"
],
"sourceType": "raw-bytecode"
}
]

@ -7,8 +7,8 @@
"debug": "<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description": "The binary subtraction can underflow.\nThe 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.", "description": "The binary subtraction can underflow.\nThe 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.",
"function": "sendeth(address,uint256)", "function": "sendeth(address,uint256)",
"max_gas_used": 78152, "max_gas_used": 78155,
"min_gas_used": 17016, "min_gas_used": 17019,
"severity": "High", "severity": "High",
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",
@ -20,8 +20,8 @@
"debug": "<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description": "The binary subtraction can underflow.\nThe 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.", "description": "The binary subtraction can underflow.\nThe 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.",
"function": "sendeth(address,uint256)", "function": "sendeth(address,uint256)",
"max_gas_used": 78152, "max_gas_used": 78155,
"min_gas_used": 17016, "min_gas_used": 17019,
"severity": "High", "severity": "High",
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",

@ -1,42 +1 @@
[ [{"issues": [{"description": {"head": "The binary subtraction can underflow.", "tail": "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."}, "extra": {}, "locations": [{"sourceMap": "567:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}, {"description": {"head": "The binary subtraction can underflow.", "tail": "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."}, "extra": {}, "locations": [{"sourceMap": "649:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xf230bec502569e8b7e7737616d0ad0f200c436624e3c223e5398c0615cd2d6b9"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "The binary subtraction can underflow.",
"tail": "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."
},
"extra": {},
"locations": [
{
"sourceMap": "567:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
},
{
"description": {
"head": "The binary subtraction can underflow.",
"tail": "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."
},
"extra": {},
"locations": [
{
"sourceMap": "649:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0xf230bec502569e8b7e7737616d0ad0f200c436624e3c223e5398c0615cd2d6b9"
],
"sourceType": "raw-bytecode"
}
]

@ -6,7 +6,7 @@
- Contract: Unknown - Contract: Unknown
- Function name: `sendeth(address,uint256)` - Function name: `sendeth(address,uint256)`
- PC address: 567 - PC address: 567
- Estimated Gas Usage: 17016 - 78152 - Estimated Gas Usage: 17019 - 78155
### Description ### Description
@ -19,7 +19,7 @@ The operands of the subtraction operation are not sufficiently constrained. The
- Contract: Unknown - Contract: Unknown
- Function name: `sendeth(address,uint256)` - Function name: `sendeth(address,uint256)`
- PC address: 649 - PC address: 649
- Estimated Gas Usage: 17016 - 78152 - Estimated Gas Usage: 17019 - 78155
### Description ### Description

@ -4,7 +4,7 @@ Severity: High
Contract: Unknown Contract: Unknown
Function name: sendeth(address,uint256) Function name: sendeth(address,uint256)
PC address: 567 PC address: 567
Estimated Gas Usage: 17016 - 78152 Estimated Gas Usage: 17019 - 78155
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.
-------------------- --------------------
@ -15,7 +15,7 @@ Severity: High
Contract: Unknown Contract: Unknown
Function name: sendeth(address,uint256) Function name: sendeth(address,uint256)
PC address: 649 PC address: 649
Estimated Gas Usage: 17016 - 78152 Estimated Gas Usage: 17019 - 78155
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.
-------------------- --------------------

@ -1,57 +1 @@
[ [{"issues": [{"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "196:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "285:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External 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."}, "extra": {}, "locations": [{"sourceMap": "285:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xb191cf6cc0d8cc37a91c9d88019cc011b932169fb5776df616e2bb9cd93b4039"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "The contract executes an external message call.",
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."
},
"extra": {},
"locations": [
{
"sourceMap": "196:1:0"
}
],
"severity": "Low",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "The contract executes an external message call.",
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."
},
"extra": {},
"locations": [
{
"sourceMap": "285:1:0"
}
],
"severity": "Low",
"swcID": "SWC-107",
"swcTitle": "Reentrancy"
},
{
"description": {
"head": "The return value of a message call is not checked.",
"tail": "External 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."
},
"extra": {},
"locations": [
{
"sourceMap": "285:1:0"
}
],
"severity": "Low",
"swcID": "SWC-104",
"swcTitle": "Unchecked Call Return Value"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0xb191cf6cc0d8cc37a91c9d88019cc011b932169fb5776df616e2bb9cd93b4039"
],
"sourceType": "raw-bytecode"
}
]

@ -1,27 +1 @@
[ [{"issues": [{"description": {"head": "The contract can be killed by anyone.", "tail": "Anyone can kill this contract and withdraw its balance to an arbitrary address."}, "extra": {}, "locations": [{"sourceMap": "146:1:0"}], "severity": "High", "swcID": "SWC-106", "swcTitle": "Unprotected SELFDESTRUCT Instruction"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x2fb801366b61a05b30550481a1c8f7d5f20de0b93d9f2f2ce2b28c4e322033c9"], "sourceType": "raw-bytecode"}]
{
"issues" : [
{
"swcTitle" : "Unprotected SELFDESTRUCT Instruction",
"locations" : [
{
"sourceMap" : "146:1:0"
}
],
"extra" : {},
"description" : {
"tail" : "Anyone can kill this contract and withdraw its balance to an arbitrary address.",
"head" : "The contract can be killed by anyone."
},
"severity" : "High",
"swcID" : "SWC-106"
}
],
"sourceFormat" : "evm-byzantium-bytecode",
"meta" : {},
"sourceType" : "raw-bytecode",
"sourceList" : [
"0x2fb801366b61a05b30550481a1c8f7d5f20de0b93d9f2f2ce2b28c4e322033c9"
]
}
]

@ -7,8 +7,8 @@
"debug": "<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description": "The binary subtraction can underflow.\nThe 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.", "description": "The binary subtraction can underflow.\nThe 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.",
"function": "sendeth(address,uint256)", "function": "sendeth(address,uint256)",
"max_gas_used": 52858, "max_gas_used": 52861,
"min_gas_used": 11912, "min_gas_used": 11915,
"severity": "High", "severity": "High",
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",
@ -20,8 +20,8 @@
"debug": "<DEBUG-DATA>", "debug": "<DEBUG-DATA>",
"description": "The binary subtraction can underflow.\nThe 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.", "description": "The binary subtraction can underflow.\nThe 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.",
"function": "sendeth(address,uint256)", "function": "sendeth(address,uint256)",
"max_gas_used": 52858, "max_gas_used": 52861,
"min_gas_used": 11912, "min_gas_used": 11915,
"severity": "High", "severity": "High",
"sourceMap": null, "sourceMap": null,
"swc-id": "101", "swc-id": "101",

@ -1,42 +1 @@
[ [{"issues": [{"description": {"head": "The binary subtraction can underflow.", "tail": "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."}, "extra": {}, "locations": [{"sourceMap": "567:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}, {"description": {"head": "The binary subtraction can underflow.", "tail": "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."}, "extra": {}, "locations": [{"sourceMap": "649:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xabef56740bf7795a9f8732e4781ebd27f2977f8a4997e3ff11cee79a4ba6c0ce"], "sourceType": "raw-bytecode"}]
{
"issues": [
{
"description": {
"head": "The binary subtraction can underflow.",
"tail": "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."
},
"extra": {},
"locations": [
{
"sourceMap": "567:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
},
{
"description": {
"head": "The binary subtraction can underflow.",
"tail": "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."
},
"extra": {},
"locations": [
{
"sourceMap": "649:1:0"
}
],
"severity": "High",
"swcID": "SWC-101",
"swcTitle": "Integer Overflow and Underflow"
}
],
"meta": {},
"sourceFormat": "evm-byzantium-bytecode",
"sourceList": [
"0xabef56740bf7795a9f8732e4781ebd27f2977f8a4997e3ff11cee79a4ba6c0ce"
],
"sourceType": "raw-bytecode"
}
]

@ -6,7 +6,7 @@
- Contract: Unknown - Contract: Unknown
- Function name: `sendeth(address,uint256)` - Function name: `sendeth(address,uint256)`
- PC address: 567 - PC address: 567
- Estimated Gas Usage: 11912 - 52858 - Estimated Gas Usage: 11915 - 52861
### Description ### Description
@ -19,7 +19,7 @@ The operands of the subtraction operation are not sufficiently constrained. The
- Contract: Unknown - Contract: Unknown
- Function name: `sendeth(address,uint256)` - Function name: `sendeth(address,uint256)`
- PC address: 649 - PC address: 649
- Estimated Gas Usage: 11912 - 52858 - Estimated Gas Usage: 11915 - 52861
### Description ### Description

@ -4,7 +4,7 @@ Severity: High
Contract: Unknown Contract: Unknown
Function name: sendeth(address,uint256) Function name: sendeth(address,uint256)
PC address: 567 PC address: 567
Estimated Gas Usage: 11912 - 52858 Estimated Gas Usage: 11915 - 52861
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.
-------------------- --------------------
@ -15,7 +15,7 @@ Severity: High
Contract: Unknown Contract: Unknown
Function name: sendeth(address,uint256) Function name: sendeth(address,uint256)
PC address: 649 PC address: 649
Estimated Gas Usage: 11912 - 52858 Estimated Gas Usage: 11915 - 52861
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.
-------------------- --------------------

Loading…
Cancel
Save