Merge pull request #767 from ConsenSys/develop

Merge for v0.19.8
pull/818/head
Bernhard Mueller 6 years ago committed by GitHub
commit 6128931242
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .circleci/config.yml
  2. 3
      .gitattributes
  3. 2
      .gitignore
  4. 4
      Dockerfile
  5. 2
      MANIFEST.in
  6. 47
      mythril/analysis/analysis_utils.py
  7. 43
      mythril/analysis/modules/delegatecall.py
  8. 141
      mythril/analysis/modules/ether_thief.py
  9. 2
      mythril/analysis/modules/exceptions.py
  10. 305
      mythril/analysis/modules/external_calls.py
  11. 24
      mythril/analysis/modules/integer.py
  12. 134
      mythril/analysis/modules/suicide.py
  13. 32
      mythril/analysis/security.py
  14. 2
      mythril/analysis/solver.py
  15. 7
      mythril/analysis/symbolic.py
  16. 19
      mythril/disassembler/disassembly.py
  17. 3
      mythril/ether/__init__.py
  18. 65
      mythril/ether/evm.py
  19. 2
      mythril/ethereum/evmcontract.py
  20. 4
      mythril/ethereum/interface/leveldb/accountindexing.py
  21. 4
      mythril/ethereum/interface/leveldb/client.py
  22. 19
      mythril/ethereum/util.py
  23. 17
      mythril/interfaces/cli.py
  24. 10
      mythril/laser/ethereum/call.py
  25. 12
      mythril/laser/ethereum/instructions.py
  26. 4
      mythril/laser/ethereum/natives.py
  27. 4
      mythril/laser/ethereum/state/account.py
  28. 179
      mythril/laser/ethereum/state/calldata.py
  29. 4
      mythril/laser/ethereum/state/environment.py
  30. 3
      mythril/laser/ethereum/state/global_state.py
  31. 4
      mythril/laser/ethereum/transaction/concolic.py
  32. 18
      mythril/laser/ethereum/transaction/symbolic.py
  33. 10
      mythril/laser/ethereum/transaction/transaction_models.py
  34. 100
      mythril/mythril.py
  35. 0
      mythril/solidity/__init__.py
  36. 6
      mythril/solidity/soliditycontract.py
  37. 375
      mythril/support/signatures.py
  38. 0
      mythril/support/support_utils.py
  39. 12
      mythril/support/truffle.py
  40. BIN
      signatures.db
  41. 396809
      signatures.json
  42. 40
      solidity_examples/BECToken.sol
  43. 104
      solidity_examples/WalletLibrary.sol
  44. 18
      solidity_examples/calls.sol
  45. 6
      solidity_examples/etherstore.sol
  46. 19
      solidity_examples/exceptions.sol
  47. 9
      solidity_examples/hashforether.sol
  48. 11
      solidity_examples/origin.sol
  49. 14
      solidity_examples/returnvalue.sol
  50. 264
      solidity_examples/rubixi.sol
  51. 5
      solidity_examples/suicide.sol
  52. 3
      solidity_examples/timelock.sol
  53. 7
      solidity_examples/token.sol
  54. 17
      solidity_examples/weak_random.sol
  55. 8
      tests/__init__.py
  56. 268
      tests/analysis/test_delegatecall.py
  57. 14
      tests/cmd_line_test.py
  58. 6
      tests/disassembler/disassembly.py
  59. 2
      tests/disassembler_test.py
  60. 23
      tests/evmcontract_test.py
  61. 14
      tests/graph_test.py
  62. 1
      tests/laser/evm_testsuite/evm_test.py
  63. 80
      tests/laser/state/calldata_test.py
  64. 15
      tests/laser/transaction/create_transaction_test.py
  65. 4
      tests/mythril_dir/config.ini
  66. BIN
      tests/mythril_dir/signatures.db.example
  67. 396809
      tests/mythril_dir/signatures.json.example
  68. 70
      tests/native_test.py
  69. 196
      tests/native_tests.sol
  70. 10
      tests/report_test.py
  71. 3
      tests/rpc_test.py
  72. 23
      tests/solidity_contract_test.py
  73. 19
      tests/svm_test.py
  74. 2
      tests/testdata/compile.py
  75. 21
      tests/testdata/input_contracts/calls.sol
  76. 10
      tests/testdata/input_contracts/constructor_assert.sol
  77. 4
      tests/testdata/input_contracts/environments.sol
  78. 11
      tests/testdata/input_contracts/ether_send.sol
  79. 19
      tests/testdata/input_contracts/exceptions.sol
  80. 15
      tests/testdata/input_contracts/kinds_of_calls.sol
  81. 5
      tests/testdata/input_contracts/metacoin.sol
  82. 19
      tests/testdata/input_contracts/multi_contracts.sol
  83. 6
      tests/testdata/input_contracts/nonascii.sol
  84. 11
      tests/testdata/input_contracts/origin.sol
  85. 9
      tests/testdata/input_contracts/overflow.sol
  86. 14
      tests/testdata/input_contracts/returnvalue.sol
  87. 264
      tests/testdata/input_contracts/rubixi.sol
  88. 5
      tests/testdata/input_contracts/suicide.sol
  89. 7
      tests/testdata/input_contracts/underflow.sol
  90. 17
      tests/testdata/input_contracts/weak_random.sol
  91. 127
      tests/testdata/outputs_expected/calls.sol.o.json
  92. 46
      tests/testdata/outputs_expected/calls.sol.o.markdown
  93. 42
      tests/testdata/outputs_expected/calls.sol.o.text
  94. 68
      tests/testdata/outputs_expected/environments.sol.o.json
  95. 27
      tests/testdata/outputs_expected/ether_send.sol.o.json
  96. 26
      tests/testdata/outputs_expected/ether_send.sol.o.markdown
  97. 22
      tests/testdata/outputs_expected/ether_send.sol.o.text
  98. 16
      tests/testdata/outputs_expected/exceptions.sol.o.json
  99. 55
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.json
  100. 4
      tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown
  101. Some files were not shown because too many files have changed in this diff Show More

@ -51,6 +51,7 @@ jobs:
environment:
LC_ALL: en_US.ASCII
LANG: en_US.ASCII
MYTHRIL_DIR: '/home/mythril'
- store_test_results:
path: /home/mythril/.tox/output

3
.gitattributes vendored

@ -1,2 +1,5 @@
tests/testdata/* linguist-detectable=false
static/* linguist-documentation
# Solidity
*.sol linguist-language=Solidity

2
.gitignore vendored

@ -176,7 +176,7 @@ lol*
coverage_html_report/
tests/testdata/outputs_current/
tests/testdata/outputs_current_laser_result/
tests/mythril_dir/signatures.json
tests/mythril_dir/signatures.db
# VSCode
.vscode

@ -1,6 +1,9 @@
FROM ubuntu:bionic
RUN apt-get update \
&& apt-get install -y \
libsqlite3-0 \
libsqlite3-dev \
&& apt-get install -y \
build-essential \
locales \
@ -16,6 +19,7 @@ RUN apt-get update \
python3-dev \
pandoc \
git \
wget \
&& ln -s /usr/bin/python3 /usr/local/bin/python
COPY ./requirements.txt /opt/mythril/requirements.txt

@ -1,2 +1,2 @@
include mythril/disassembler/signatures.json
include mythril/disassembler/signatures.db
include mythril/analysis/templates/*

@ -1,47 +0,0 @@
import re
from typing import List
from z3 import *
from mythril.laser.ethereum.transaction import ContractCreationTransaction
from mythril.laser.ethereum.state.global_state import GlobalState
def get_non_creator_constraints(state: GlobalState) -> (List, bool):
"""
Get constraints which say that the caller isn't the creator of the contract
:param state: The state
:return: tuple of (constraints, bool) where the bool says whether the caller is constrained or not
"""
not_creator_constraints = []
creator = None
if isinstance(
state.world_state.transaction_sequence[0], ContractCreationTransaction
):
creator = state.world_state.transaction_sequence[0].caller
if creator is not None:
for transaction in state.world_state.transaction_sequence[1:]:
not_creator_constraints.append(
Not(Extract(159, 0, transaction.caller) == Extract(159, 0, creator))
)
not_creator_constraints.append(
Not(Extract(159, 0, transaction.caller) == 0)
)
else:
for transaction in state.world_state.transaction_sequence:
not_creator_constraints.append(
Not(Extract(159, 0, transaction.caller) == 0)
)
if not has_caller_check_constraint(state.mstate.constraints):
return [], True
return not_creator_constraints, False
def has_caller_check_constraint(constraints: List) -> bool:
"""
Checks whether the caller is constrained to a value or not
"""
for constraint in constraints:
if re.search(r"caller", str(constraint)) and re.search(
r"[0-9]{20}", str(constraint)
):
return False
return True

@ -37,9 +37,6 @@ class DelegateCallModule(DetectionModule):
if meminstart.type == VarType.CONCRETE:
issues += self._concrete_call(call, state, address, meminstart)
if call.to.type == VarType.SYMBOLIC:
issues += self._symbolic_call(call, state, address, statespace)
return issues
def _concrete_call(self, call, state, address, meminstart):
@ -68,45 +65,5 @@ class DelegateCallModule(DetectionModule):
return [issue]
def _symbolic_call(self, call, state, address, statespace):
issue = Issue(
contract=call.node.contract_name,
function_name=call.node.function_name,
address=address,
swc_id=DELEGATECALL_TO_UNTRUSTED_CONTRACT,
bytecode=state.environment.code.bytecode,
title=call.type + " to a user-supplied address",
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
if "calldata" in str(call.to):
issue.description = "This contract delegates execution to a contract address obtained from calldata."
else:
m = re.search(r"storage_([a-z0-9_&^]+)", str(call.to))
if m:
idx = m.group(1)
func = statespace.find_storage_write(
state.environment.active_account.address, idx
)
if func:
issue.description = (
"This contract delegates execution to a contract address in storage slot "
+ str(idx)
+ ". This storage slot can be written to by calling the function `"
+ func
+ "`."
)
else:
logging.debug(
"[DELEGATECALL] No storage writes to index " + str(idx)
)
issue.description += " Be aware that the called contract gets unrestricted access to this contract's state."
return [issue]
detector = DelegateCallModule()

@ -1,13 +1,13 @@
from mythril.analysis.ops import *
from mythril.analysis import solver
from mythril.analysis.analysis_utils import get_non_creator_constraints
from mythril.analysis.report import Issue
from mythril.analysis.swc_data import UNPROTECTED_ETHER_WITHDRAWAL
from mythril.analysis.modules.base import DetectionModule
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.exceptions import UnsatError
from z3 import BitVecVal, UGT
from z3 import BitVecVal, UGT, Sum
import logging
from copy import copy
DESCRIPTION = """
@ -22,7 +22,56 @@ An issue is reported if:
"""
ARBITRARY_SENDER_ADDRESS = 0xAAAAAAAABBBBBBBBBCCCCCCCDDDDDDDDEEEEEEEE
def _analyze_state(state):
instruction = state.get_current_instruction()
node = state.node
if instruction["opcode"] != "CALL":
return []
call_value = state.mstate.stack[-3]
target = state.mstate.stack[-2]
eth_sent_total = BitVecVal(0, 256)
constraints = copy(node.constraints)
for tx in state.world_state.transaction_sequence:
if tx.caller == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF:
# There's sometimes no overflow check on balances added.
# But we don't care about attacks that require more 2^^256 ETH to be sent.
constraints += [BVAddNoOverflow(eth_sent_total, tx.call_value, False)]
eth_sent_total = Sum(eth_sent_total, tx.call_value)
constraints += [UGT(call_value, eth_sent_total), target == state.environment.sender]
try:
transaction_sequence = solver.get_transaction_sequence(state, constraints)
debug = str(transaction_sequence)
issue = Issue(
contract=node.contract_name,
function_name=node.function_name,
address=instruction["address"],
swc_id=UNPROTECTED_ETHER_WITHDRAWAL,
title="Ether thief",
_type="Warning",
bytecode=state.environment.code.bytecode,
description="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.",
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
except UnsatError:
logging.debug("[ETHER_THIEF] no model found")
return []
return [issue]
class EtherThief(DetectionModule):
@ -32,83 +81,17 @@ class EtherThief(DetectionModule):
swc_id=UNPROTECTED_ETHER_WITHDRAWAL,
hooks=["CALL"],
description=DESCRIPTION,
entrypoint="callback",
)
self._issues = []
def execute(self, state: GlobalState):
self._issues.extend(_analyze_state(state))
return self.issues
def execute(self, state_space):
logging.debug("Executing module: %s", self.name)
issues = []
for k in state_space.nodes:
node = state_space.nodes[k]
for state in node.states:
issues += self._analyze_state(state, node)
return issues
@staticmethod
def _analyze_state(state, node):
issues = []
instruction = state.get_current_instruction()
if instruction["opcode"] != "CALL":
return []
call_value = state.mstate.stack[-3]
target = state.mstate.stack[-2]
not_creator_constraints, constrained = get_non_creator_constraints(state)
if constrained:
return []
eth_sent_total = BitVecVal(0, 256)
for tx in state.world_state.transaction_sequence[1:]:
eth_sent_total += tx.call_value
try:
model = solver.get_model(
node.constraints
+ not_creator_constraints
+ [
UGT(call_value, eth_sent_total),
state.environment.sender == ARBITRARY_SENDER_ADDRESS,
target == state.environment.sender,
]
)
transaction_sequence = solver.get_transaction_sequence(
state,
node.constraints
+ not_creator_constraints
+ [
call_value > eth_sent_total,
state.environment.sender == ARBITRARY_SENDER_ADDRESS,
target == state.environment.sender,
],
)
debug = "Transaction Sequence: " + str(transaction_sequence)
issue = Issue(
contract=node.contract_name,
function_name=node.function_name,
address=instruction["address"],
swc_id=UNPROTECTED_ETHER_WITHDRAWAL,
title="Ether thief",
_type="Warning",
bytecode=state.environment.code.bytecode,
description="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.",
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
issues.append(issue)
except UnsatError:
logging.debug("[ETHER_THIEF] no model found")
return issues
@property
def issues(self):
return self._issues
detector = EtherThief()

@ -42,7 +42,7 @@ class ReachableExceptionsModule(DetectionModule):
"Use `require()` for regular input checking."
)
debug = "Transaction Sequence: " + str(
debug = str(
solver.get_transaction_sequence(state, node.constraints)
)

@ -1,218 +1,111 @@
from z3 import *
from mythril.analysis.ops import *
from mythril.analysis.report import Issue
from mythril.analysis import solver
from mythril.analysis.swc_data import REENTRANCY
from mythril.analysis.modules.base import DetectionModule
import re
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.exceptions import UnsatError
import logging
from mythril.laser.ethereum.cfg import JumpType
DESCRIPTION = """
class ExternalCallModule(DetectionModule):
def __init__(self, max_search_depth=64):
Search for low level calls (e.g. call.value()) that forward all gas to the callee.
Report a warning if the callee address can be set by the sender, otherwise create
an informational issue.
"""
def _analyze_state(state):
node = state.node
gas = state.mstate.stack[-1]
to = state.mstate.stack[-2]
address = state.get_current_instruction()["address"]
try:
constraints = node.constraints
transaction_sequence = solver.get_transaction_sequence(
state, constraints + [UGT(gas, 2300)]
)
# Check whether we can also set the callee address
try:
constraints += [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF]
transaction_sequence = solver.get_transaction_sequence(state, constraints)
debug = str(transaction_sequence)
description = (
"The contract executes a function call with high gas to a user-supplied address. "
"Note that the callee can contain arbitrary code and may re-enter any function in this contract. "
"Review the business logic carefully to prevent unanticipated effects on the contract state."
)
issue = Issue(
contract=node.contract_name,
function_name=node.function_name,
address=address,
swc_id=REENTRANCY,
title="External call to user-supplied address",
_type="Warning",
bytecode=state.environment.code.bytecode,
description=description,
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
except UnsatError:
logging.debug(
"[EXTERNAL_CALLS] Callee address cannot be modified. Reporting informational issue."
)
debug = str(transaction_sequence)
description = (
"The contract executes a function call to an external address. "
"Verify that the code at this address is trusted and immutable."
)
issue = Issue(
contract=node.contract_name,
function_name=state.node.function_name,
address=address,
swc_id=REENTRANCY,
title="External call",
_type="Informational",
bytecode=state.environment.code.bytecode,
description=description,
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
except UnsatError:
logging.debug("[EXTERNAL_CALLS] No model found.")
return []
return [issue]
class ExternalCalls(DetectionModule):
def __init__(self):
super().__init__(
name="External Calls",
name="External calls",
swc_id=REENTRANCY,
hooks=["CALL"],
description="Check for call.value()() to external addresses",
description=(DESCRIPTION),
entrypoint="callback",
)
self.max_search_depth = max_search_depth
self.calls_visited = []
def search_children(
self, statespace, node, transaction_id, start_index=0, depth=0, results=None
):
if results is None:
results = []
logging.debug("SEARCHING NODE %d", node.uid)
if depth < self.max_search_depth:
n_states = len(node.states)
if n_states > start_index:
for j in range(start_index, n_states):
if (
node.states[j].get_current_instruction()["opcode"] == "SSTORE"
and node.states[j].current_transaction.id == transaction_id
):
results.append(
node.states[j].get_current_instruction()["address"]
)
children = []
for edge in statespace.edges:
if edge.node_from == node.uid and edge.type != JumpType.Transaction:
children.append(statespace.nodes[edge.node_to])
if len(children):
for node in children:
results += self.search_children(
statespace,
node,
transaction_id,
depth=depth + 1,
results=results,
)
return results
def execute(self, statespace):
issues = []
for call in statespace.calls:
state = call.state
address = state.get_current_instruction()["address"]
if call.type == "CALL":
logging.debug(
"[EXTERNAL_CALLS] Call to: %s, value = %s, gas = %s"
% (str(call.to), str(call.value), str(call.gas))
)
if (
call.to.type == VarType.SYMBOLIC
and (call.gas.type == VarType.CONCRETE and call.gas.val > 2300)
or (
call.gas.type == VarType.SYMBOLIC
and "2300" not in str(call.gas)
)
):
description = "This contract executes a message call to "
target = str(call.to)
user_supplied = False
if "calldata" in target or "caller" in target:
if "calldata" in target:
description += (
"an address provided as a function argument. "
)
else:
description += "the address of the transaction sender. "
user_supplied = True
else:
m = re.search(r"storage_([a-z0-9_&^]+)", str(call.to))
if m:
idx = m.group(1)
func = statespace.find_storage_write(
state.environment.active_account.address, idx
)
if func:
description += (
"an address found at storage slot "
+ str(idx)
+ ". "
+ "This storage slot can be written to by calling the function `"
+ func
+ "`. "
)
user_supplied = True
if user_supplied:
description += (
"Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. "
"Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state."
)
issue = Issue(
contract=call.node.contract_name,
function_name=call.node.function_name,
address=address,
title="Message call to external contract",
_type="Warning",
description=description,
bytecode=state.environment.code.bytecode,
swc_id=REENTRANCY,
gas_used=(
state.mstate.min_gas_used,
state.mstate.max_gas_used,
),
)
else:
description += "to another contract. Make sure that the called contract is trusted and does not execute user-supplied code."
issue = Issue(
contract=call.node.contract_name,
function_name=call.node.function_name,
address=address,
title="Message call to external contract",
_type="Informational",
description=description,
bytecode=state.environment.code.bytecode,
swc_id=REENTRANCY,
gas_used=(
state.mstate.min_gas_used,
state.mstate.max_gas_used,
),
)
issues.append(issue)
if address not in self.calls_visited:
self.calls_visited.append(address)
logging.debug(
"[EXTERNAL_CALLS] Checking for state changes starting from "
+ call.node.function_name
)
# Check for SSTORE in remaining instructions in current node & nodes down the CFG
state_change_addresses = self.search_children(
statespace,
call.node,
call.state.current_transaction.id,
call.state_index + 1,
depth=0,
results=[],
)
logging.debug(
"[EXTERNAL_CALLS] Detected state changes at addresses: "
+ str(state_change_addresses)
)
if len(state_change_addresses):
for address in state_change_addresses:
description = (
"The contract account state is changed after an external call. "
"Consider that the called contract could re-enter the function before this "
"state change takes place. This can lead to business logic vulnerabilities."
)
issue = Issue(
contract=call.node.contract_name,
function_name=call.node.function_name,
address=address,
title="State change after external call",
_type="Warning",
description=description,
bytecode=state.environment.code.bytecode,
swc_id=REENTRANCY,
gas_used=(
state.mstate.min_gas_used,
state.mstate.max_gas_used,
),
)
issues.append(issue)
return issues
detector = ExternalCallModule()
self._issues = []
def execute(self, state: GlobalState):
self._issues.extend(_analyze_state(state))
return self.issues
@property
def issues(self):
return self._issues
detector = ExternalCalls()

@ -108,8 +108,8 @@ class IntegerOverflowUnderflowModule(DetectionModule):
operator
)
try:
issue.debug = "Transaction Sequence: " + str(
solver.get_transaction_sequence(state, node.constraints)
issue.debug = str(
solver.get_transaction_sequence(state, node.constraints + [constraint])
)
except UnsatError:
return issues
@ -167,33 +167,19 @@ class IntegerOverflowUnderflowModule(DetectionModule):
constraints = copy.deepcopy(node.constraints)
# Filter for patterns that indicate benign underflows
# Pattern 1: (96 + calldatasize_MAIN) - (96), where (96 + calldatasize_MAIN) would underflow if calldatasize is very large.
# Pattern 2: (256*If(1 & storage_0 == 0, 1, 0)) - 1, this would underlow if storage_0 = 0
if type(op0) == int and type(op1) == int:
return []
if re.search(r"calldatasize_", str(op0)):
return []
if re.search(r"256\*.*If\(1", str(op0), re.DOTALL) or re.search(
r"256\*.*If\(1", str(op1), re.DOTALL
):
return []
if re.search(r"32 \+.*calldata", str(op0), re.DOTALL) or re.search(
r"32 \+.*calldata", str(op1), re.DOTALL
):
return []
logging.debug(
"[INTEGER_UNDERFLOW] Checking SUB {0}, {1} at address {2}".format(
str(op0), str(op1), str(instruction["address"])
)
)
allowed_types = [int, BitVecRef, BitVecNumRef]
if type(op0) in allowed_types and type(op1) in allowed_types:
constraints.append(UGT(op1, op0))
constraints.append(Not(BVSubNoUnderflow(op0, op1, signed=False)))
try:
model = solver.get_model(constraints)
@ -223,7 +209,7 @@ class IntegerOverflowUnderflowModule(DetectionModule):
"The subtraction can result in an integer underflow.\n"
)
issue.debug = "Transaction Sequence: " + str(
issue.debug = str(
solver.get_transaction_sequence(state, node.constraints)
)
issues.append(issue)

@ -1,20 +1,60 @@
from mythril.analysis import solver
from mythril.analysis.analysis_utils import get_non_creator_constraints
from mythril.analysis.ops import *
from mythril.analysis.report import Issue
from mythril.analysis.swc_data import UNPROTECTED_SELFDESTRUCT
from mythril.exceptions import UnsatError
from mythril.analysis.modules.base import DetectionModule
from mythril.laser.ethereum.transaction import ContractCreationTransaction
import re
from mythril.laser.ethereum.state.global_state import GlobalState
import logging
DESCRIPTION = """
Check if the contact can be 'accidentally' killed by anyone.
For kill-able contracts, also check whether it is possible to direct the contract balance to the attacker.
"""
MODULE DESCRIPTION:
"""
def _analyze_state(state):
logging.info("Suicide module: Analyzing suicide instruction")
node = state.node
instruction = state.get_current_instruction()
to = state.mstate.stack[-1]
logging.debug("[SUICIDE] SUICIDE in function " + node.function_name)
try:
try:
transaction_sequence = solver.get_transaction_sequence(
state,
node.constraints + [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF],
)
description = "Anyone can kill this contract and withdraw its balance to their own account."
except UnsatError:
transaction_sequence = solver.get_transaction_sequence(
state, node.constraints
)
description = (
"The contract can be killed by anyone. Don't accidentally kill it."
)
debug = str(transaction_sequence)
issue = Issue(
contract=node.contract_name,
function_name=node.function_name,
address=instruction["address"],
swc_id=UNPROTECTED_SELFDESTRUCT,
bytecode=state.environment.code.bytecode,
title="Unchecked SUICIDE",
_type="Warning",
description=description,
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
return [issue]
except UnsatError:
logging.info("[UNCHECKED_SUICIDE] no model found")
return []
class SuicideModule(DetectionModule):
@ -23,82 +63,18 @@ class SuicideModule(DetectionModule):
name="Unprotected Suicide",
swc_id=UNPROTECTED_SELFDESTRUCT,
hooks=["SUICIDE"],
description=(
"Check for SUICIDE instructions that either can be reached by anyone, "
"or where msg.sender is checked against a tainted storage index (i.e. "
"there's a write to that index is unconstrained by msg.sender)."
),
description=(DESCRIPTION),
entrypoint="callback",
)
self._issues = []
def execute(self, state_space):
logging.debug("Executing module: UNCHECKED_SUICIDE")
issues = []
for k in state_space.nodes:
node = state_space.nodes[k]
for state in node.states:
issues += self._analyze_state(state, node)
return issues
def _analyze_state(self, state, node):
issues = []
instruction = state.get_current_instruction()
if instruction["opcode"] != "SUICIDE":
return []
to = state.mstate.stack[-1]
logging.debug("[UNCHECKED_SUICIDE] suicide in function " + node.function_name)
description = "A reachable SUICIDE instruction was detected. "
if "caller" in str(to):
description += "The remaining Ether is sent to the caller's address.\n"
elif "storage" in str(to):
description += "The remaining Ether is sent to a stored address.\n"
elif "calldata" in str(to):
description += "The remaining Ether is sent to an address provided as a function argument.\n"
elif type(to) == BitVecNumRef:
description += "The remaining Ether is sent to: " + hex(to.as_long()) + "\n"
else:
description += "The remaining Ether is sent to: " + str(to) + "\n"
not_creator_constraints, constrained = get_non_creator_constraints(state)
if constrained:
return []
try:
model = solver.get_model(node.constraints + not_creator_constraints)
debug = "Transaction Sequence: " + str(
solver.get_transaction_sequence(
state, node.constraints + not_creator_constraints
)
)
issue = Issue(
contract=node.contract_name,
function_name=node.function_name,
address=instruction["address"],
swc_id=UNPROTECTED_SELFDESTRUCT,
bytecode=state.environment.code.bytecode,
title="Unchecked SUICIDE",
_type="Warning",
description=description,
debug=debug,
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
)
issues.append(issue)
except UnsatError:
logging.debug("[UNCHECKED_SUICIDE] no model found")
def execute(self, state: GlobalState):
self._issues.extend(_analyze_state(state))
return self.issues
return issues
@property
def issues(self):
return self._issues
detector = SuicideModule()

@ -9,6 +9,12 @@ import logging
OPCODE_LIST = [c[0] for _, c in opcodes.items()]
def reset_callback_modules():
modules = get_detection_modules("callback")
for module in modules:
module.detector._issues = []
def get_detection_module_hooks():
hook_dict = defaultdict(list)
_modules = get_detection_modules(entrypoint="callback")
@ -35,17 +41,18 @@ def get_detection_modules(entrypoint, include_modules=()):
_modules = []
if not include_modules:
for loader, name, _ in pkgutil.walk_packages(modules.__path__):
module = loader.find_module(name).load_module(name)
if module.__name__ != "base" and module.detector.entrypoint == entrypoint:
_modules.append(module)
for loader, module_name, _ in pkgutil.walk_packages(modules.__path__):
if module_name != "base":
module = importlib.import_module(
"mythril.analysis.modules." + module_name
)
if module.detector.entrypoint == entrypoint:
_modules.append(module)
else:
for module_name in include_modules:
module = importlib.import_module(module_name, modules)
_modules.append(module)
module = importlib.import_module("mythril.analysis.modules." + module_name)
if module.__name__ != "base" and module.detector.entrypoint == entrypoint:
_modules.append(module)
logging.info("Found %s detection modules", len(_modules))
return _modules
@ -61,4 +68,11 @@ def fire_lasers(statespace, module_names=()):
logging.info("Executing " + module.detector.name)
issues += module.detector.execute(statespace)
for module in get_detection_modules(
entrypoint="callback", include_modules=module_names
):
logging.debug("Retrieving results for " + module.detector.name)
issues += module.detector.issues
reset_callback_modules()
return issues

@ -103,7 +103,7 @@ def get_transaction_sequence(global_state, constraints):
concrete_transactions[tx_id]["calldata"] = "0x" + "".join(
[
hex(b)[2:] if len(hex(b)) % 2 == 0 else "0" + hex(b)[2:]
for b in transaction.call_data.concretized(model)
for b in transaction.call_data.concrete(model)
]
)

@ -1,9 +1,8 @@
from mythril.analysis.security import get_detection_module_hooks
from mythril.laser.ethereum import svm
from mythril.laser.ethereum.state.account import Account
from mythril.ether.soliditycontract import SolidityContract, ETHContract
from mythril.solidity.soliditycontract import SolidityContract, EVMContract
import copy
import logging
from .ops import get_variable, SStore, Call, VarType
from mythril.laser.ethereum.strategy.basic import (
DepthFirstSearchStrategy,
@ -61,14 +60,14 @@ class SymExecWrapper:
transaction_count=transaction_count,
)
self.laser.register_hooks(
hook_type="post", hook_dict=get_detection_module_hooks()
hook_type="pre", hook_dict=get_detection_module_hooks()
)
if isinstance(contract, SolidityContract):
self.laser.sym_exec(
creation_code=contract.creation_code, contract_name=contract.name
)
elif isinstance(contract, ETHContract) and contract.creation_code:
elif isinstance(contract, EVMContract) and contract.creation_code:
self.laser.sym_exec(
creation_code=contract.creation_code, contract_name=contract.name
)

@ -1,6 +1,6 @@
from mythril.ether import util
from mythril.ethereum import util
from mythril.disassembler import asm
from mythril.support.signatures import SignatureDb
from mythril.support.signatures import SignatureDB
import logging
@ -23,16 +23,9 @@ class Disassembly(object):
self.function_name_to_address = {}
self.address_to_function_name = {}
signatures = {}
try:
# open from default locations
signatures = SignatureDb(
enable_online_lookup=enable_online_lookup
) # control if you want to have online signature hash lookups
except FileNotFoundError:
logging.info(
"Missing function signature file. Resolving of function names from signature file disabled."
)
# open from default locations
# control if you want to have online signature hash lookups
signatures = SignatureDB(enable_online_lookup=enable_online_lookup)
# Need to take from PUSH1 to PUSH4 because solc seems to remove excess 0s at the beginning for optimizing
jump_table_indices = asm.find_op_code_sequence(
@ -54,7 +47,7 @@ class Disassembly(object):
def get_function_info(
index: int, instruction_list: list, signature_database: SignatureDb
index: int, instruction_list: list, signature_database: SignatureDB
) -> (str, int, str):
"""
Finds the function information for a call table entry

@ -1,3 +0,0 @@
import time
start_time = time.time()

@ -1,65 +0,0 @@
from ethereum import vm, messages, transactions
from ethereum.state import State
from ethereum.slogging import get_logger
from mythril.ether import util
from logging import StreamHandler
from io import StringIO
import re
def trace(code, calldata=""):
log_handlers = [
"eth.vm.op",
"eth.vm.op.stack",
"eth.vm.op.memory",
"eth.vm.op.storage",
]
output = StringIO()
stream_handler = StreamHandler(output)
for handler in log_handlers:
log_vm_op = get_logger(handler)
log_vm_op.setLevel("TRACE")
log_vm_op.addHandler(stream_handler)
addr = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF01234567")
state = State()
ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr, 0, addr))
message = vm.Message(addr, addr, 0, 21000, calldata)
vm.vm_execute(ext, message, util.safe_decode(code))
stream_handler.flush()
ret = output.getvalue()
lines = ret.split("\n")
state_trace = []
for line in lines:
m = re.search(r"pc=b\'(\d+)\'.*op=([A-Z0-9]+)", line)
if m:
pc = m.group(1)
op = m.group(2)
m = re.match(r".*stack=(\[.*?\])", line)
if m:
stackitems = re.findall(r"b\'(\d+)\'", m.group(1))
stack = "["
if len(stackitems):
for i in range(0, len(stackitems) - 1):
stack += hex(int(stackitems[i])) + ", "
stack += hex(int(stackitems[-1]))
stack += "]"
else:
stack = "[]"
if re.match(r"^PUSH.*", op):
val = re.search(r"pushvalue=(\d+)", line).group(1)
pushvalue = hex(int(val))
state_trace.append(
{"pc": pc, "op": op, "stack": stack, "pushvalue": pushvalue}
)
else:
state_trace.append({"pc": pc, "op": op, "stack": stack})
return state_trace

@ -4,7 +4,7 @@ import persistent
import re
class ETHContract(persistent.Persistent):
class EVMContract(persistent.Persistent):
def __init__(
self, code="", creation_code="", name="Unknown", enable_online_lookup=False
):

@ -1,5 +1,5 @@
import logging
from mythril import ether
from mythril import ethereum
import time
from ethereum.messages import Log
import rlp
@ -156,7 +156,7 @@ class AccountIndexer(object):
processed += BATCH_SIZE
blockNum = min(blockNum + BATCH_SIZE, self.lastBlock + 1)
cost_time = time.time() - ether.start_time
cost_time = time.time() - ethereum.start_time
print(
"%d blocks processed (in %d seconds), %d unique addresses found, next block: %d"
% (processed, cost_time, count, min(self.lastBlock, blockNum))

@ -10,7 +10,7 @@ from ethereum import utils
from ethereum.block import BlockHeader, Block
from mythril.ethereum.interface.leveldb.state import State
from mythril.ethereum.interface.leveldb.eth_db import ETH_DB
from mythril.ether.ethcontract import ETHContract
from mythril.ethereum.evmcontract import EVMContract
from mythril.exceptions import AddressNotFoundError
# Per https://github.com/ethereum/go-ethereum/blob/master/core/rawdb/schema.go
@ -182,7 +182,7 @@ class EthLevelDB(object):
for account in self.reader._get_head_state().get_all_accounts():
if account.code is not None:
code = _encode_hex(account.code)
contract = ETHContract(code, enable_online_lookup=False)
contract = EVMContract(code, enable_online_lookup=False)
yield contract, account.address, account.balance

@ -6,6 +6,7 @@ from subprocess import Popen, PIPE
import binascii
import os
import json
from pathlib import Path
def safe_decode(hex_encoded_string):
@ -72,10 +73,14 @@ def get_indexed_address(index):
def solc_exists(version):
solc_binary = os.path.join(
os.environ["HOME"], ".py-solc/solc-v" + version, "bin/solc"
)
if os.path.exists(solc_binary):
return True
else:
return False
solc_binaries = [
os.path.join(
os.environ.get("HOME", str(Path.home())),
".py-solc/solc-v" + version,
"bin/solc",
), # py-solc setup
"/usr/bin/solc", # Ubuntu PPA setup
]
for solc_path in solc_binaries:
if os.path.exists(solc_path):
return solc_path

@ -200,13 +200,12 @@ def main():
)
rpc = parser.add_argument_group("RPC options")
rpc.add_argument(
"-i", action="store_true", help="Preset: Infura Node service (Mainnet)"
)
rpc.add_argument(
"--rpc",
help="custom RPC settings",
metavar="HOST:PORT / ganache / infura-[network_name]",
default="infura-mainnet",
)
rpc.add_argument(
"--rpctls", type=bool, default=False, help="RPC connection over TLS"
@ -290,12 +289,7 @@ def main():
if args.address:
# Establish RPC connection if necessary
if args.i:
mythril.set_api_rpc_infura()
elif args.rpc:
mythril.set_api_rpc(rpc=args.rpc, rpctls=args.rpctls)
elif not (args.dynld or not args.no_onchain_storage_access):
mythril.set_api_rpc_localhost()
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(
@ -331,9 +325,11 @@ def main():
if args.code:
# Load from bytecode
address, _ = mythril.load_from_bytecode(args.code, args.bin_runtime)
code = args.code[2:] if args.code.startswith("0x") else args.code
address, _ = mythril.load_from_bytecode(code, args.bin_runtime)
elif args.codefile:
bytecode = "".join([l.strip() for l in args.codefile if len(l.strip()) > 0])
bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode
address, _ = mythril.load_from_bytecode(bytecode, args.bin_runtime)
elif args.address:
# Get bytecode from a contract address
@ -389,7 +385,6 @@ def main():
max_depth=args.max_depth,
execution_timeout=args.execution_timeout,
create_timeout=args.create_timeout,
transaction_count=1,
)
try:

@ -3,7 +3,11 @@ from typing import Union
from z3 import simplify, ExprRef, Extract
import mythril.laser.ethereum.util as util
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import CalldataType, Calldata
from mythril.laser.ethereum.state.calldata import (
CalldataType,
SymbolicCalldata,
ConcreteCalldata,
)
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.support.loader import DynLoader
import re
@ -174,12 +178,12 @@ def get_call_data(
starting_calldata.append(Extract(j + 7, j, elem))
i += 1
call_data = Calldata(transaction_id, starting_calldata)
call_data = ConcreteCalldata(transaction_id, starting_calldata)
call_data_type = CalldataType.CONCRETE
logging.debug("Calldata: " + str(call_data))
except TypeError:
logging.debug("Unsupported symbolic calldata offset")
call_data_type = CalldataType.SYMBOLIC
call_data = Calldata("{}_internalcall".format(transaction_id))
call_data = SymbolicCalldata("{}_internalcall".format(transaction_id))
return call_data, call_data_type

@ -42,7 +42,7 @@ from mythril.laser.ethereum.evm_exceptions import (
)
from mythril.laser.ethereum.gas import OPCODE_GAS
from mythril.laser.ethereum.keccak import KeccakFunctionManager
from mythril.laser.ethereum.state.calldata import CalldataType, Calldata
from mythril.laser.ethereum.state.calldata import CalldataType
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.transaction import (
MessageCallTransaction,
@ -131,7 +131,7 @@ class Instruction:
def evaluate(self, global_state: GlobalState, post=False) -> List[GlobalState]:
""" Performs the mutation for this instruction """
# Generalize some ops
logging.debug("Evaluating {}".format(self.op_code))
# logging.debug("Evaluating {}".format(self.op_code))
op = self.op_code.lower()
if self.op_code.startswith("PUSH"):
op = "push"
@ -458,10 +458,9 @@ class Instruction:
environment = global_state.environment
op0 = state.stack.pop()
value, constraints = environment.calldata.get_word_at(op0)
value = environment.calldata.get_word_at(op0)
state.stack.append(value)
state.constraints.extend(constraints)
return [global_state]
@ -541,9 +540,8 @@ class Instruction:
i_data = dstart
new_memory = []
for i in range(size):
value, constraints = environment.calldata[i_data]
value = environment.calldata[i_data]
new_memory.append(value)
state.constraints.extend(constraints)
i_data = (
i_data + 1 if isinstance(i_data, int) else simplify(i_data + 1)
@ -706,7 +704,7 @@ class Instruction:
if size == 0 and isinstance(
global_state.current_transaction, ContractCreationTransaction
):
if concrete_code_offset >= len(global_state.environment.code.bytecode) // 2:
if concrete_code_offset >= len(bytecode) // 2:
global_state.mstate.mem_extend(concrete_memory_offset, 1)
global_state.mstate.memory[
concrete_memory_offset

@ -8,7 +8,7 @@ from ethereum.utils import ecrecover_to_pub
from py_ecc.secp256k1 import N as secp256k1n
from rlp.utils import ALL_BYTES
from mythril.laser.ethereum.state.calldata import Calldata
from mythril.laser.ethereum.state.calldata import BaseCalldata
from mythril.laser.ethereum.util import bytearray_to_int, sha3, get_concrete_int
from z3 import Concat, simplify
@ -88,7 +88,7 @@ def identity(data: Union[bytes, str, List[int]]) -> bytes:
return result
def native_contracts(address: int, data: Calldata):
def native_contracts(address: int, data: BaseCalldata):
"""
takes integer address 1, 2, 3, 4
"""

@ -1,6 +1,6 @@
from typing import Dict, Union, Any, KeysView
from z3 import BitVec, ExprRef
from z3 import BitVec, BitVecVal, ExprRef
from mythril.disassembler.disassembly import Disassembly
@ -41,7 +41,7 @@ class Storage:
pass
if self.concrete:
return 0
self._storage[item] = BitVec("storage_" + str(item), 256)
self._storage[item] = BitVecVal(0, 256)
return self._storage[item]
def __setitem__(self, key: str, value: ExprRef) -> None:

@ -1,17 +1,7 @@
from enum import Enum
from typing import Union, Any
from z3 import (
BitVecVal,
BitVecRef,
BitVecSort,
BitVec,
Implies,
simplify,
Concat,
UGT,
Array,
)
from z3.z3types import Z3Exception
from z3 import BitVecVal, BitVecRef, BitVec, simplify, Concat, If, ExprRef
from z3.z3types import Z3Exception, Model
from mythril.laser.ethereum.util import get_concrete_int
@ -21,84 +11,133 @@ class CalldataType(Enum):
SYMBOLIC = 2
class Calldata:
class BaseCalldata:
"""
Calldata class representing the calldata of a transaction
Base calldata class
This represents the calldata provided when sending a transaction to a contract
"""
def __init__(self, tx_id, starting_calldata=None):
"""
Constructor for Calldata
:param tx_id: unique value representing the transaction the calldata is for
:param starting_calldata: byte array representing the concrete calldata of a transaction
"""
def __init__(self, tx_id):
self.tx_id = tx_id
if starting_calldata is not None:
self._calldata = []
self.calldatasize = BitVecVal(len(starting_calldata), 256)
self.concrete = True
else:
self._calldata = Array(
"{}_calldata".format(self.tx_id), BitVecSort(256), BitVecSort(8)
)
self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id), 256)
self.concrete = False
if self.concrete:
for calldata_byte in starting_calldata:
if type(calldata_byte) == int:
self._calldata.append(BitVecVal(calldata_byte, 8))
else:
self._calldata.append(calldata_byte)
def concretized(self, model):
result = []
for i in range(
get_concrete_int(model.eval(self.calldatasize, model_completion=True))
):
result.append(
get_concrete_int(model.eval(self._calldata[i], model_completion=True))
)
@property
def calldatasize(self) -> ExprRef:
"""
:return: Calldata size for this calldata object
"""
result = self.size
if isinstance(result, int):
return BitVecVal(result, 256)
return result
def get_word_at(self, index: int):
return self[index : index + 32]
def get_word_at(self, offset: int) -> ExprRef:
""" Gets word at offset"""
return self[offset : offset + 32]
def __getitem__(self, item: Union[int, slice]) -> Any:
if isinstance(item, int) or isinstance(item, ExprRef):
return self._load(item)
if isinstance(item, slice):
start, step, stop = item.start, item.step, item.stop
start = 0 if item.start is None else item.start
step = 1 if item.step is None else item.step
stop = self.size if item.stop is None else item.stop
try:
if start is None:
start = 0
if step is None:
step = 1
if stop is None:
stop = self.calldatasize
current_index = (
start if isinstance(start, BitVecRef) else BitVecVal(start, 256)
)
dataparts = []
parts = []
while simplify(current_index != stop):
dataparts.append(self[current_index])
parts.append(self._load(current_index))
current_index = simplify(current_index + step)
except Z3Exception:
raise IndexError("Invalid Calldata Slice")
values, constraints = zip(*dataparts)
result_constraints = []
for c in constraints:
result_constraints.extend(c)
return simplify(Concat(values)), result_constraints
return simplify(Concat(parts))
raise ValueError
def _load(self, item: Union[int, ExprRef]) -> Any:
raise NotImplementedError()
@property
def size(self) -> Union[ExprRef, int]:
""" Returns the exact size of this calldata, this is not normalized"""
raise NotImplementedError()
def concrete(self, model: Model) -> list:
""" Returns a concrete version of the calldata using the provided model"""
raise NotImplementedError
class ConcreteCalldata(BaseCalldata):
def __init__(self, tx_id: int, calldata: list):
"""
Initializes the ConcreteCalldata object
:param tx_id: Id of the transaction that the calldata is for.
:param calldata: The concrete calldata content
"""
self._calldata = calldata
super().__init__(tx_id)
if self.concrete:
def _load(self, item: Union[int, ExprRef]) -> Any:
if isinstance(item, int):
try:
return self._calldata[get_concrete_int(item)], ()
return self._calldata[item]
except IndexError:
return BitVecVal(0, 8), ()
else:
constraints = [
Implies(self._calldata[item] != 0, UGT(self.calldatasize, item))
]
return 0
value = BitVecVal(0x0, 8)
for i in range(self.size):
value = If(item == i, self._calldata[i], value)
return value
def concrete(self, model: Model) -> list:
return self._calldata
@property
def size(self) -> int:
return len(self._calldata)
class SymbolicCalldata(BaseCalldata):
def __init__(self, tx_id: int):
"""
Initializes the SymbolicCalldata object
:param tx_id: Id of the transaction that the calldata is for.
"""
self._reads = []
self._size = BitVec("calldatasize", 256)
super().__init__(tx_id)
def _load(self, item: Union[int, ExprRef], clean=False) -> Any:
x = BitVecVal(item, 256) if isinstance(item, int) else item
symbolic_base_value = If(
x > self._size,
BitVecVal(0, 8),
BitVec("{}_calldata_{}".format(self.tx_id, str(item)), 8),
)
return_value = symbolic_base_value
for r_index, r_value in self._reads:
return_value = If(r_index == item, r_value, return_value)
if not clean:
self._reads.append((item, symbolic_base_value))
return simplify(return_value)
def concrete(self, model: Model) -> list:
concrete_length = get_concrete_int(model.eval(self.size, model_completion=True))
result = []
for i in range(concrete_length):
value = self._load(i, clean=True)
c_value = get_concrete_int(model.eval(value, model_completion=True))
result.append(c_value)
return result
return self._calldata[item], constraints
@property
def size(self) -> ExprRef:
return self._size

@ -3,7 +3,7 @@ from typing import Dict
from z3 import ExprRef, BitVecVal
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import Calldata, CalldataType
from mythril.laser.ethereum.state.calldata import CalldataType, BaseCalldata
class Environment:
@ -15,7 +15,7 @@ class Environment:
self,
active_account: Account,
sender: ExprRef,
calldata: Calldata,
calldata: BaseCalldata,
gasprice: ExprRef,
callvalue: ExprRef,
origin: ExprRef,

@ -21,6 +21,7 @@ class GlobalState:
machine_state=None,
transaction_stack=None,
last_return_data=None,
annotations=None,
):
""" Constructor for GlobalState"""
self.node = node
@ -32,6 +33,7 @@ class GlobalState:
self.transaction_stack = transaction_stack if transaction_stack else []
self.op_code = ""
self.last_return_data = last_return_data
self.annotations = annotations or []
def __copy__(self) -> "GlobalState":
world_state = copy(self.world_state)
@ -45,6 +47,7 @@ class GlobalState:
mstate,
transaction_stack=transaction_stack,
last_return_data=self.last_return_data,
annotations=self.annotations,
)
@property

@ -6,7 +6,7 @@ from mythril.laser.ethereum.transaction.transaction_models import (
)
from z3 import BitVec
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.calldata import Calldata, CalldataType
from mythril.laser.ethereum.state.calldata import CalldataType, ConcreteCalldata
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.state.global_state import GlobalState
@ -42,7 +42,7 @@ def execute_message_call(
code=Disassembly(code),
caller=caller_address,
callee_account=open_world_state[callee_address],
call_data=Calldata(next_transaction_id, data),
call_data=ConcreteCalldata(next_transaction_id, data),
call_data_type=CalldataType.SYMBOLIC,
call_value=value,
)

@ -1,9 +1,13 @@
from z3 import BitVec, Extract, Not
from z3 import BitVec, BitVecVal
from logging import debug
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.cfg import Node, Edge, JumpType
from mythril.laser.ethereum.state.calldata import CalldataType, Calldata
from mythril.laser.ethereum.state.calldata import (
CalldataType,
BaseCalldata,
SymbolicCalldata,
)
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.transaction.transaction_models import (
MessageCallTransaction,
@ -12,6 +16,10 @@ from mythril.laser.ethereum.transaction.transaction_models import (
)
CREATOR_ADDRESS = 0xAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFEAFFE
ATTACKER_ADDRESS = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
def execute_message_call(laser_evm, callee_address: str) -> None:
""" Executes a message call transaction from all open states """
# TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
@ -30,9 +38,9 @@ def execute_message_call(laser_evm, callee_address: str) -> None:
gas_price=BitVec("gas_price{}".format(next_transaction_id), 256),
gas_limit=8000000, # block gas limit
origin=BitVec("origin{}".format(next_transaction_id), 256),
caller=BitVec("caller{}".format(next_transaction_id), 256),
caller=BitVecVal(ATTACKER_ADDRESS, 256),
callee_account=open_world_state[callee_address],
call_data=Calldata(next_transaction_id),
call_data=SymbolicCalldata(next_transaction_id),
call_data_type=CalldataType.SYMBOLIC,
call_value=BitVec("call_value{}".format(next_transaction_id), 256),
)
@ -64,7 +72,7 @@ def execute_contract_creation(
gas_limit=8000000, # block gas limit
origin=BitVec("origin{}".format(next_transaction_id), 256),
code=Disassembly(contract_initialization_code),
caller=BitVec("creator{}".format(next_transaction_id), 256),
caller=BitVecVal(CREATOR_ADDRESS, 256),
callee_account=new_account,
call_data=[],
call_data_type=CalldataType.SYMBOLIC,

@ -2,7 +2,11 @@ import logging
from typing import Union
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.calldata import Calldata
from mythril.laser.ethereum.state.calldata import (
BaseCalldata,
ConcreteCalldata,
SymbolicCalldata,
)
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.state.global_state import GlobalState
@ -75,9 +79,9 @@ class BaseTransaction:
self.caller = caller
self.callee_account = callee_account
if call_data is None and init_call_data:
self.call_data = Calldata(self.id, call_data)
self.call_data = ConcreteCalldata(self.id, call_data)
else:
self.call_data = call_data if isinstance(call_data, Calldata) else None
self.call_data = call_data if isinstance(call_data, BaseCalldata) else None
self.call_data_type = (
call_data_type
if call_data_type is not None

@ -9,6 +9,7 @@ import logging
import json
import os
import re
from pathlib import Path
from ethereum import utils
import codecs
@ -17,9 +18,9 @@ import solc
from configparser import ConfigParser
import platform
from mythril.ether import util
from mythril.ether.ethcontract import ETHContract
from mythril.ether.soliditycontract import SolidityContract, get_contracts_from_file
from mythril.ethereum import util
from mythril.ethereum.evmcontract import EVMContract
from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file
from mythril.ethereum.interface.rpc.client import EthJsonRpc
from mythril.ethereum.interface.rpc.exceptions import ConnectionError
from mythril.support import signatures
@ -94,27 +95,10 @@ class Mythril(object):
self.mythril_dir = self._init_mythril_dir()
self.sigs = {}
try:
# tries mythril_dir/signatures.json by default (provide path= arg to make this configurable)
self.sigs = signatures.SignatureDb(
enable_online_lookup=self.enable_online_lookup
)
except FileNotFoundError as e:
logging.info(str(e))
# Create empty db file if none exists
f = open(os.path.join(self.mythril_dir, "signatures.json"), "w")
f.write("{}")
f.close()
self.sigs = signatures.SignatureDb(
enable_online_lookup=self.enable_online_lookup
)
except json.JSONDecodeError as e:
raise CriticalError(str(e))
# tries mythril_dir/signatures.db by default (provide path= arg to make this configurable)
self.sigs = signatures.SignatureDB(
enable_online_lookup=self.enable_online_lookup
)
self.solc_binary = self._init_solc_binary(solv)
self.config_path = os.path.join(self.mythril_dir, "config.ini")
@ -223,34 +207,33 @@ class Mythril(object):
# Figure out solc binary and version
# Only proper versions are supported. No nightlies, commits etc (such as available in remix)
if version:
# tried converting input to semver, seemed not necessary so just slicing for now
if version == str(solc.main.get_solc_version())[:6]:
logging.info("Given version matches installed version")
try:
solc_binary = os.environ["SOLC"]
except KeyError:
solc_binary = "solc"
else:
if util.solc_exists(version):
logging.info("Given version is already installed")
else:
try:
solc.install_solc("v" + version)
except SolcError:
raise CriticalError(
"There was an error when trying to install the specified solc version"
)
if not version:
return os.environ.get("SOLC") or "solc"
solc_binary = os.path.join(
os.environ["HOME"], ".py-solc/solc-v" + version, "bin/solc"
)
logging.info("Setting the compiler to " + str(solc_binary))
# tried converting input to semver, seemed not necessary so just slicing for now
main_version = solc.main.get_solc_version_string()
main_version_number = re.match(r"\d+.\d+.\d+", main_version)
if main_version is None:
raise CriticalError(
"Could not extract solc version from string {}".format(main_version)
)
if version == main_version_number:
logging.info("Given version matches installed version")
solc_binary = os.environ.get("SOLC") or "solc"
else:
try:
solc_binary = os.environ["SOLC"]
except KeyError:
solc_binary = "solc"
solc_binary = util.solc_exists(version)
if solc_binary:
logging.info("Given version is already installed")
else:
try:
solc.install_solc("v" + version)
except SolcError:
raise CriticalError(
"There was an error when trying to install the specified solc version"
)
logging.info("Setting the compiler to %s", solc_binary)
return solc_binary
def set_api_leveldb(self, leveldb):
@ -319,11 +302,13 @@ class Mythril(object):
print(self.eth_db.contract_hash_to_address(hash))
def load_from_bytecode(self, code, bin_runtime=False):
address = util.get_indexed_address(0)
def load_from_bytecode(self, code, bin_runtime=False, address=None):
if address is None:
address = util.get_indexed_address(0)
if bin_runtime:
self.contracts.append(
ETHContract(
EVMContract(
code=code,
name="MAIN",
enable_online_lookup=self.enable_online_lookup,
@ -331,7 +316,7 @@ class Mythril(object):
)
else:
self.contracts.append(
ETHContract(
EVMContract(
creation_code=code,
name="MAIN",
enable_online_lookup=self.enable_online_lookup,
@ -360,7 +345,7 @@ class Mythril(object):
)
else:
self.contracts.append(
ETHContract(
EVMContract(
code,
name=address,
enable_online_lookup=self.enable_online_lookup,
@ -386,12 +371,9 @@ class Mythril(object):
try:
# import signatures from solidity source
self.sigs.import_from_solidity_source(
self.sigs.import_solidity_file(
file, solc_binary=self.solc_binary, solc_args=self.solc_args
)
# Save updated function signatures
self.sigs.write() # dump signatures to disk (previously opened file or default location)
if contract_name is not None:
contract = SolidityContract(
input_file=file,

@ -1,6 +1,6 @@
import mythril.laser.ethereum.util as helper
from mythril.ether.ethcontract import ETHContract
from mythril.ether.util import get_solc_json
from mythril.ethereum.evmcontract import EVMContract
from mythril.ethereum.util import get_solc_json
from mythril.exceptions import NoContractFoundError
@ -42,7 +42,7 @@ def get_contracts_from_file(input_file, solc_args=None, solc_binary="solc"):
raise NoContractFoundError
class SolidityContract(ETHContract):
class SolidityContract(EVMContract):
def __init__(self, input_file, name=None, solc_args=None, solc_binary="solc"):
data = get_solc_json(input_file, solc_args=solc_args, solc_binary=solc_binary)

@ -3,11 +3,11 @@
"""mythril.py: Function Signature Database
"""
import os
import json
import time
import logging
import sqlite3
from typing import List
from collections import defaultdict
from subprocess import Popen, PIPE
from mythril.exceptions import CompilerError
@ -22,280 +22,199 @@ except ImportError:
FourByteDirectoryOnlineLookupError = Exception
try:
# Posix based file locking (Linux, Ubuntu, MacOS, etc.)
import fcntl
def lock_file(f, exclusive=False):
if f.mode == "r" and exclusive:
raise Exception("Please use non exclusive mode for reading")
flag = fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH
fcntl.lockf(f, flag)
def unlock_file(f):
return
except ImportError:
# Windows file locking
# TODO: confirm the existence or non existence of shared locks in windows msvcrt and make changes based on that
import msvcrt
class SQLiteDB(object):
"""
Simple CM for sqlite3 databases. Commits everything at exit.
"""
def file_size(f):
return os.path.getsize(os.path.realpath(f.name))
def __init__(self, path):
self.path = path
self.conn = None
self.cursor = None
def lock_file(f, exclusive=False):
if f.mode == "r" and exclusive:
raise Exception("Please use non exclusive mode for reading")
msvcrt.locking(f.fileno(), msvcrt.LK_RLCK, file_size(f))
def __enter__(self):
self.conn = sqlite3.connect(self.path)
self.cursor = self.conn.cursor()
return self.cursor
def unlock_file(f):
msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, file_size(f))
def __exit__(self, exc_class, exc, traceback):
self.conn.commit()
self.conn.close()
def __repr__(self):
return "<SQLiteDB path={}>".format(self.path)
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class SignatureDB(object):
def __init__(self, enable_online_lookup: bool = False, path: str = None) -> None:
self.enable_online_lookup = enable_online_lookup
self.online_lookup_miss = set()
self.online_lookup_timeout = 0
if path is None:
self.path = os.environ.get("MYTHRIL_DIR") or os.path.join(
os.path.expanduser("~"), ".mythril"
)
self.path = os.path.join(self.path, "signatures.db")
logging.info("Using signature database at %s", self.path)
# NOTE: Creates a new DB file if it doesn't exist already
with SQLiteDB(self.path) as cur:
cur.execute(
(
"CREATE TABLE IF NOT EXISTS signatures"
"(byte_sig VARCHAR(10), text_sig VARCHAR(255),"
"PRIMARY KEY (byte_sig, text_sig))"
)
)
class SignatureDb(object, metaclass=Singleton):
def __init__(self, enable_online_lookup=False):
def __getitem__(self, item: str) -> List[str]:
"""
Constr
:param enable_online_lookup: enable onlien signature hash lookup
Provide dict interface db[sighash]
:param item: 4-byte signature string
:return: list of matching text signature strings
"""
self.signatures = defaultdict(list) # signatures in-mem cache
self.signatures_file = None
self.enable_online_lookup = (
enable_online_lookup
) # enable online funcsig resolving
# temporarily track misses from onlinedb to avoid requesting the same non-existent sighash multiple times
self.online_lookup_miss = set()
# flag the online directory as unavailable for some time
self.online_directory_unavailable_until = 0
self.open()
return self.get(byte_sig=item)
def open(self, path=None):
@staticmethod
def _normalize_byte_sig(byte_sig: str) -> str:
"""
Open a function signature db from json file
:param path: specific path to signatures.json; default mythril location if not specified
:return: self
Adds a leading 0x to the byte signature if it's not already there.
:param byte_sig: 4-byte signature string
:return: normalized byte signature string
"""
if not path:
# try default locations
try:
mythril_dir = os.environ["MYTHRIL_DIR"]
except KeyError:
mythril_dir = os.path.join(os.path.expanduser("~"), ".mythril")
path = os.path.join(mythril_dir, "signatures.json")
# store early to allow error handling to access the place we tried to load the file
self.signatures_file = path
if not os.path.exists(path):
logging.debug("Signatures: file not found: %s" % path)
raise FileNotFoundError(
(
"Could not find signature file in {}. Function name resolution disabled.\n"
"Consider replacing it with the pre-initialized database at "
"https://raw.githubusercontent.com/ConsenSys/mythril/master/signatures.json"
).format(path)
if not byte_sig.startswith("0x"):
byte_sig = "0x" + byte_sig
if not len(byte_sig) == 10:
raise ValueError(
"Invalid byte signature %s, must have 10 characters", byte_sig
)
return byte_sig
with open(path, "r") as f:
lock_file(f)
try:
sigs = json.load(f)
except json.JSONDecodeError as e:
# reraise with path
raise json.JSONDecodeError(
"Invalid JSON in the signatures file {}: {}".format(path, str(e))
)
finally:
unlock_file(f)
# assert signature file format
for sighash, funcsig in sigs.items():
if (
not sighash.startswith("0x")
or len(sighash) != 10
or not isinstance(funcsig, list)
):
raise ValueError(
"Malformed signature file at {}. {}: {} is not a valid entry".format(
path, sighash, funcsig
)
)
self.signatures = defaultdict(list, sigs)
return self
def update_signatures(self, new_signatures):
for sighash, funcsigs in new_signatures.items():
# eliminate duplicates
updated_funcsigs = set(funcsigs + self.signatures[sighash])
self.signatures[sighash] = list(updated_funcsigs)
def write(self, path=None, sync=True):
def add(self, byte_sig: str, text_sig: str) -> None:
"""
Write signatures database as json to file
:param path: specify path otherwise update the file that was loaded with open()
:param sync: lock signature file, load contents and merge it into memcached sighash db, then save it
:return: self
Adds a new byte - text signature pair to the database.
:param byte_sig: 4-byte signature string
:param text_sig: resolved text signature
:return:
"""
path = path or self.signatures_file
directory = os.path.split(path)[0]
if sync and os.path.exists(path):
# reload and save if file exists
with open(path, "r") as f:
lock_file(f)
try:
sigs = json.load(f)
finally:
unlock_file(f)
self.update_signatures(sigs)
if directory and not os.path.exists(directory):
os.makedirs(directory) # create folder structure if not existS
if not os.path.exists(path): # creates signatures.json file if it doesn't exist
open(path, "w").close()
with open(path, "r+") as f: # placing 'w+' here will result in race conditions
lock_file(f, exclusive=True)
try:
json.dump(self.signatures, f, indent=4, sort_keys=True)
finally:
unlock_file(f)
return self
byte_sig = self._normalize_byte_sig(byte_sig)
with SQLiteDB(self.path) as cur:
# ignore new row if it's already in the DB (and would cause a unique constraint error)
cur.execute(
"INSERT OR IGNORE INTO signatures (byte_sig, text_sig) VALUES (?,?)",
(byte_sig, text_sig),
)
def get(self, sighash, timeout=2):
def get(self, byte_sig: str, online_timeout: int = 2) -> List[str]:
"""
get a function signature for a sighash
Get a function text signature for a byte signature
1) try local cache
2) try online lookup (if enabled; if not flagged as unavailable)
:param sighash: function signature hash as hexstr
:param timeout: online lookup timeout
:return: list of matching function signatures
:param byte_sig: function signature hash as hexstr
:param online_timeout: online lookup timeout
:return: list of matching function text signatures
"""
if not sighash.startswith("0x"):
sighash = "0x%s" % sighash # normalize sighash format
byte_sig = self._normalize_byte_sig(byte_sig)
# try lookup in the local DB
with SQLiteDB(self.path) as cur:
cur.execute("SELECT text_sig FROM signatures WHERE byte_sig=?", (byte_sig,))
text_sigs = cur.fetchall()
if text_sigs:
return [t[0] for t in text_sigs]
# abort if we're not allowed to check 4byte or we already missed
# the signature, or we're on a timeout
if (
self.enable_online_lookup
and not self.signatures.get(sighash)
and sighash not in self.online_lookup_miss
and time.time() > self.online_directory_unavailable_until
not self.enable_online_lookup
or byte_sig in self.online_lookup_miss
or time.time() < self.online_lookup_timeout
):
# online lookup enabled, and signature not in cache, sighash was not a miss earlier, and online directory not down
logging.debug(
"Signatures: performing online lookup for sighash %r" % sighash
)
try:
funcsigs = SignatureDb.lookup_online(
sighash, timeout=timeout
) # might return multiple sigs
if funcsigs:
# only store if we get at least one result
self.update_signatures({sighash: funcsigs})
else:
# miss
self.online_lookup_miss.add(sighash)
except FourByteDirectoryOnlineLookupError as fbdole:
self.online_directory_unavailable_until = (
time.time() + 2 * 60
) # wait at least 2 mins to try again
logging.warning(
"online function signature lookup not available. will not try to lookup hash for the next 2 minutes. exception: %r"
% fbdole
)
if sighash not in self.signatures:
return []
if type(self.signatures[sighash]) != list:
return [self.signatures[sighash]]
return self.signatures[sighash]
def __getitem__(self, item):
"""
Provide dict interface Signatures()[sighash]
:param item: sighash
:return: list of matching signatures
"""
return self.get(sighash=item)
try:
text_sigs = self.lookup_online(byte_sig=byte_sig, timeout=online_timeout)
if not text_sigs:
self.online_lookup_miss.add(byte_sig)
return []
else:
for resolved in text_sigs:
self.add(byte_sig, resolved)
return text_sigs
except FourByteDirectoryOnlineLookupError as fbdole:
# wait at least 2 mins to try again
self.online_lookup_timeout = time.time() + 2 * 60
logging.warning("Online lookup failed, not retrying for 2min: %s", fbdole)
return []
def import_from_solidity_source(
self, file_path, solc_binary="solc", solc_args=None
def import_solidity_file(
self, file_path: str, solc_binary: str = "solc", solc_args: str = None
):
"""
Import Function Signatures from solidity source files
:param file_path: solidity source code file path
:return: self
:return:
"""
self.update_signatures(
self.get_sigs_from_file(
file_path, solc_binary=solc_binary, solc_args=solc_args
sigs = {}
cmd = [solc_binary, "--hashes", file_path]
if solc_args:
cmd.extend(solc_args.split())
try:
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
ret = p.returncode
if ret != 0:
raise CompilerError(
"Solc has experienced a fatal error (code {}).\n\n{}".format(
ret, stderr.decode("utf-8")
)
)
except FileNotFoundError:
raise CompilerError(
(
"Compiler not found. Make sure that solc is installed and in PATH, "
"or the SOLC environment variable is set."
)
)
)
return self
stdout = stdout.decode("unicode_escape").split("\n")
for line in stdout:
# the ':' need not be checked but just to be sure
if all(map(lambda x: x in line, ["(", ")", ":"])):
sigs["0x" + line.split(":")[0]] = [line.split(":")[1].strip()]
logging.debug("Signatures: found %d signatures after parsing" % len(sigs))
# update DB with what we've found
for byte_sig, text_sigs in sigs.items():
for text_sig in text_sigs:
self.add(byte_sig, text_sig)
@staticmethod
def lookup_online(sighash, timeout=None, proxies=None):
def lookup_online(byte_sig: str, timeout: int, proxies=None) -> List[str]:
"""
Lookup function signatures from 4byte.directory.
//tintinweb: the smart-contract-sanctuary project dumps contracts from etherscan.io and feeds them into
4bytes.directory.
https://github.com/tintinweb/smart-contract-sanctuary
:param sighash: function signature hash as hexstr
:param byte_sig: function signature hash as hexstr
:param timeout: optional timeout for online lookup
:param proxies: optional proxy servers for online lookup
:return: a list of matching function signatures for this hash
"""
if not ethereum_input_decoder:
return None
return []
return list(
ethereum_input_decoder.decoder.FourByteDirectory.lookup_signatures(
sighash, timeout=timeout, proxies=proxies
byte_sig, timeout=timeout, proxies=proxies
)
)
@staticmethod
def get_sigs_from_file(file_name, solc_binary="solc", solc_args=None):
"""
:param file_name: accepts a filename
:return: their signature mappings
"""
sigs = {}
cmd = [solc_binary, "--hashes", file_name]
if solc_args:
cmd.extend(solc_args.split())
try:
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
ret = p.returncode
if ret != 0:
raise CompilerError(
"Solc experienced a fatal error (code %d).\n\n%s"
% (ret, stderr.decode("UTF-8"))
)
except FileNotFoundError:
raise CompilerError(
"Compiler not found. Make sure that solc is installed and in PATH, or set the SOLC environment variable."
)
stdout = stdout.decode("unicode_escape").split("\n")
for line in stdout:
if (
"(" in line and ")" in line and ":" in line
): # the ':' need not be checked but just to be sure
sigs["0x" + line.split(":")[0]] = [line.split(":")[1].strip()]
logging.debug("Signatures: found %d signatures after parsing" % len(sigs))
return sigs
def __repr__(self):
return "<SignatureDB path='{}' enable_online_lookup={}>".format(
self.path, self.enable_online_lookup
)

@ -5,14 +5,13 @@ import sys
import json
import logging
from ethereum.utils import sha3
from mythril.ether.ethcontract import ETHContract
from mythril.ether.soliditycontract import SourceMapping
from mythril.exceptions import CriticalError
from mythril.ethereum.evmcontract import EVMContract
from mythril.solidity.soliditycontract import SourceMapping
from mythril.analysis.security import fire_lasers
from mythril.analysis.symbolic import SymExecWrapper
from mythril.analysis.report import Report
from mythril.ether import util
from mythril.ethereum import util
from mythril.laser.ethereum.util import get_instruction_index
@ -44,7 +43,7 @@ def analyze_truffle_project(sigs, args):
continue
get_sigs_from_truffle(sigs, contractdata)
ethcontract = ETHContract(bytecode, name=name)
ethcontract = EVMContract(bytecode, name=name)
address = util.get_indexed_address(0)
sym = SymExecWrapper(
@ -139,8 +138,7 @@ def get_sigs_from_truffle(sigs, contract_data):
function_name = abi["name"]
list_of_args = ",".join([input["type"] for input in abi["inputs"]])
signature = function_name + "(" + list_of_args + ")"
sigs.signatures["0x" + sha3(signature)[:4].hex()] = [signature]
sigs.write()
sigs.add("0x" + sha3(signature)[:4].hex(), signature)
def get_mappings(source, deployed_source_map):

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -1,29 +1,29 @@
pragma solidity ^0.4.16;
pragma solidity 0.5.0;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
@ -37,7 +37,7 @@ library SafeMath {
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) public constant returns (uint256);
function balanceOf(address who) public returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
@ -63,7 +63,7 @@ contract BasicToken is ERC20Basic {
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value);
return true;
}
@ -72,7 +72,7 @@ contract BasicToken is ERC20Basic {
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public constant returns (uint256 balance) {
function balanceOf(address _owner) public returns (uint256 balance) {
return balances[_owner];
}
}
@ -82,7 +82,7 @@ contract BasicToken is ERC20Basic {
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) public constant returns (uint256);
function allowance(address owner, address spender) public returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
@ -115,7 +115,7 @@ contract StandardToken is ERC20, BasicToken {
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(_from, _to, _value);
emit Transfer(_from, _to, _value);
return true;
}
@ -131,7 +131,7 @@ contract StandardToken is ERC20, BasicToken {
*/
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
emit Approval(msg.sender, _spender, _value);
return true;
}
@ -141,7 +141,7 @@ contract StandardToken is ERC20, BasicToken {
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
function allowance(address _owner, address _spender) public returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
@ -162,7 +162,7 @@ contract Ownable {
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
constructor() public {
owner = msg.sender;
}
@ -182,7 +182,7 @@ contract Ownable {
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
@ -220,7 +220,7 @@ contract Pausable is Ownable {
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
emit Pause();
}
/**
@ -228,7 +228,7 @@ contract Pausable is Ownable {
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
emit Unpause();
}
}
@ -252,7 +252,7 @@ contract PausableToken is StandardToken, Pausable {
return super.approve(_spender, _value);
}
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
function batchTransfer(address[] memory _receivers, uint256 _value) public whenNotPaused returns (bool) {
uint cnt = _receivers.length;
uint256 amount = uint256(cnt) * _value;
require(cnt > 0 && cnt <= 20);
@ -261,7 +261,7 @@ contract PausableToken is StandardToken, Pausable {
balances[msg.sender] = balances[msg.sender].sub(amount);
for (uint i = 0; i < cnt; i++) {
balances[_receivers[i]] = balances[_receivers[i]].add(_value);
Transfer(msg.sender, _receivers[i], _value);
emit Transfer(msg.sender, _receivers[i], _value);
}
return true;
}
@ -287,12 +287,12 @@ contract BecToken is PausableToken {
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
*/
function BecToken() {
constructor() public {
totalSupply = 7000000000 * (10**(uint256(decimals)));
balances[msg.sender] = totalSupply; // Give the creator all initial tokens
}
function () {
function () external {
//if ether is sent to this address, send it back.
revert();
}

@ -9,7 +9,7 @@
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
pragma solidity ^0.4.9;
pragma solidity 0.5.0;
contract WalletEvents {
// EVENTS
@ -50,15 +50,15 @@ contract WalletAbi {
function changeRequirement(uint _newRequired) external;
function isOwner(address _addr) constant returns (bool);
function isOwner(address _addr) public returns (bool);
function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool);
function hasConfirmed(bytes32 _operation, address _owner) external returns (bool);
// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
function setDailyLimit(uint _newLimit) external;
function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash);
function confirm(bytes32 _h) returns (bool o_success);
function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32 o_hash);
function confirm(bytes32 _h) public returns (bool o_success);
}
contract WalletLibrary is WalletEvents {
@ -96,15 +96,15 @@ contract WalletLibrary is WalletEvents {
// METHODS
// gets called when no other function matches
function() payable {
function() external payable {
// just being sent some cash?
if (msg.value > 0)
Deposit(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
// constructor is given number of sigs required to do protected "onlymanyowners" transactions
// as well as the selection of addresses capable of confirming them.
function initMultiowned(address[] _owners, uint _required) only_uninitialized {
function initMultiowned(address[] memory _owners, uint _required) public only_uninitialized {
m_numOwners = _owners.length + 1;
m_owners[1] = uint(msg.sender);
m_ownerIndex[uint(msg.sender)] = 1;
@ -122,16 +122,16 @@ contract WalletLibrary is WalletEvents {
// make sure they're an owner
if (ownerIndex == 0) return;
uint ownerIndexBit = 2**ownerIndex;
var pending = m_pending[_operation];
PendingState memory pending = m_pending[_operation];
if (pending.ownersDone & ownerIndexBit > 0) {
pending.yetNeeded++;
pending.ownersDone -= ownerIndexBit;
Revoke(msg.sender, _operation);
emit Revoke(msg.sender, _operation);
}
}
// Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external {
function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) external {
if (isOwner(_to)) return;
uint ownerIndex = m_ownerIndex[uint(_from)];
if (ownerIndex == 0) return;
@ -140,10 +140,10 @@ contract WalletLibrary is WalletEvents {
m_owners[ownerIndex] = uint(_to);
m_ownerIndex[uint(_from)] = 0;
m_ownerIndex[uint(_to)] = ownerIndex;
OwnerChanged(_from, _to);
emit OwnerChanged(_from, _to);
}
function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
function addOwner(address _owner) onlymanyowners(keccak256(msg.data)) external {
if (isOwner(_owner)) return;
clearPending();
@ -154,10 +154,10 @@ contract WalletLibrary is WalletEvents {
m_numOwners++;
m_owners[m_numOwners] = uint(_owner);
m_ownerIndex[uint(_owner)] = m_numOwners;
OwnerAdded(_owner);
emit OwnerAdded(_owner);
}
function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
function removeOwner(address _owner) onlymanyowners(keccak256(msg.data)) external {
uint ownerIndex = m_ownerIndex[uint(_owner)];
if (ownerIndex == 0) return;
if (m_required > m_numOwners - 1) return;
@ -166,27 +166,27 @@ contract WalletLibrary is WalletEvents {
m_ownerIndex[uint(_owner)] = 0;
clearPending();
reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot
OwnerRemoved(_owner);
emit OwnerRemoved(_owner);
}
function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external {
function changeRequirement(uint _newRequired) onlymanyowners(keccak256(msg.data)) external {
if (_newRequired > m_numOwners) return;
m_required = _newRequired;
clearPending();
RequirementChanged(_newRequired);
emit RequirementChanged(_newRequired);
}
// Gets an owner by 0-indexed position (using numOwners as the count)
function getOwner(uint ownerIndex) external constant returns (address) {
function getOwner(uint ownerIndex) external view returns (address) {
return address(m_owners[ownerIndex + 1]);
}
function isOwner(address _addr) constant returns (bool) {
function isOwner(address _addr) public view returns (bool) {
return m_ownerIndex[uint(_addr)] > 0;
}
function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) {
var pending = m_pending[_operation];
function hasConfirmed(bytes32 _operation, address _owner) external view returns (bool) {
PendingState memory pending = m_pending[_operation];
uint ownerIndex = m_ownerIndex[uint(_owner)];
// make sure they're an owner
@ -198,85 +198,87 @@ contract WalletLibrary is WalletEvents {
}
// constructor - stores initial daily limit and records the present day's index.
function initDaylimit(uint _limit) only_uninitialized {
function initDaylimit(uint _limit) public only_uninitialized {
m_dailyLimit = _limit;
m_lastDay = today();
}
// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
function setDailyLimit(uint _newLimit) onlymanyowners(keccak256(msg.data)) external {
m_dailyLimit = _newLimit;
}
// resets the amount already spent today. needs many of the owners to confirm.
function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
m_spentToday = 0;
}
// throw unless the contract is not yet initialized.
modifier only_uninitialized { if (m_numOwners > 0) throw; _; }
modifier only_uninitialized { require(m_numOwners > 0); _; }
// constructor - just pass on the owner array to the multiowned and
// the limit to daylimit
function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
function initWallet(address[] memory _owners, uint _required, uint _daylimit) public only_uninitialized {
initDaylimit(_daylimit);
initMultiowned(_owners, _required);
}
// kills the contract sending everything to `_to`.
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
suicide(_to);
function kill(address payable _to) onlymanyowners(keccak256(msg.data)) external {
selfdestruct(_to);
}
// Outside-visible transact entry point. Executes transaction immediately if below daily spend limit.
// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
// and _data arguments). They still get the option of using them if they want, anyways.
function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) {
function execute(address _to, uint _value, bytes calldata _data) external onlyowner returns (bytes32 o_hash) {
// first, take the opportunity to check that we're under the daily limit.
if ((_data.length == 0 && underLimit(_value)) || m_required == 1) {
// yes - just execute the call.
address created;
if (_to == 0) {
if (_to == address(0)) {
created = create(_value, _data);
} else {
if (!_to.call.value(_value)(_data))
throw;
(bool success, bytes memory data) = _to.call.value(_value)(_data);
require(success);
}
SingleTransact(msg.sender, _value, _to, _data, created);
emit SingleTransact(msg.sender, _value, _to, _data, created);
} else {
// determine our operation hash.
o_hash = sha3(msg.data, block.number);
o_hash = keccak256(abi.encode(msg.data, block.number));
// store if it's new
if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) {
if (m_txs[o_hash].to == address(0) && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) {
m_txs[o_hash].to = _to;
m_txs[o_hash].value = _value;
m_txs[o_hash].data = _data;
}
if (!confirm(o_hash)) {
ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data);
emit ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data);
}
}
}
function create(uint _value, bytes _code) internal returns (address o_addr) {
function create(uint _value, bytes memory _code) internal returns (address o_addr) {
uint256 o_size;
assembly {
o_addr := create(_value, add(_code, 0x20), mload(_code))
jumpi(0xdeadbeef, iszero(extcodesize(o_addr)))
o_size := extcodesize(o_addr)
}
require(o_size != 0);
}
// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
// to determine the body of the transaction from the hash provided.
function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) {
if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) {
function confirm(bytes32 _h) public onlymanyowners(_h) returns (bool o_success) {
if (m_txs[_h].to != address(0) || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) {
address created;
if (m_txs[_h].to == 0) {
if (m_txs[_h].to == address(0)) {
created = create(m_txs[_h].value, m_txs[_h].data);
} else {
if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data))
throw;
(bool success, bytes memory data) = m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data);
require(success);
}
MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created);
emit MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created);
delete m_txs[_h];
return true;
}
@ -288,9 +290,9 @@ contract WalletLibrary is WalletEvents {
// determine what index the present sender is:
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
// make sure they're an owner
if (ownerIndex == 0) return;
if (ownerIndex == 0) return false;
var pending = m_pending[_operation];
PendingState memory pending = m_pending[_operation];
// if we're not yet working on this operation, switch over and reset the confirmation status.
if (pending.yetNeeded == 0) {
// reset count of confirmations needed.
@ -304,7 +306,7 @@ contract WalletLibrary is WalletEvents {
uint ownerIndexBit = 2**ownerIndex;
// make sure we (the message sender) haven't confirmed this operation previously.
if (pending.ownersDone & ownerIndexBit == 0) {
Confirmation(msg.sender, _operation);
emit Confirmation(msg.sender, _operation);
// ok - check if count is enough to go ahead.
if (pending.yetNeeded <= 1) {
// enough confirmations: reset and run interior.
@ -354,7 +356,7 @@ contract WalletLibrary is WalletEvents {
}
// determines today's index.
function today() private constant returns (uint) { return now / 1 days; }
function today() private view returns (uint) { return now / 1 days; }
function clearPending() internal {
uint length = m_pendingIndex.length;
@ -370,7 +372,7 @@ contract WalletLibrary is WalletEvents {
}
// FIELDS
address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe;
address _walletLibrary = 0xCAfEcAfeCAfECaFeCaFecaFecaFECafECafeCaFe;
// the number of owners that must confirm the same operation before it is run.
uint public m_required;
@ -384,7 +386,7 @@ contract WalletLibrary is WalletEvents {
// list of owners
uint[256] m_owners;
uint constant c_maxOwners = 250;
uint c_maxOwners = 250;
// index on the list of owners to allow reverse lookup
mapping(uint => uint) m_ownerIndex;
// the ongoing operations.

@ -1,4 +1,4 @@
pragma solidity ^0.4.17;
pragma solidity 0.5.0;
contract Caller {
@ -8,28 +8,28 @@ contract Caller {
uint256 statevar;
function Caller(address addr) {
constructor(address addr) public {
fixed_address = addr;
}
function thisisfine() public {
fixed_address.call();
fixed_address.call("");
}
function reentrancy() public {
fixed_address.call();
fixed_address.call("");
statevar = 0;
}
function calluseraddress(address addr) {
addr.call();
function calluseraddress(address addr) public {
addr.call("");
}
function callstoredaddress() {
stored_address.call();
function callstoredaddress() public {
stored_address.call("");
}
function setstoredaddress(address addr) {
function setstoredaddress(address addr) public {
stored_address = addr;
}

@ -1,3 +1,6 @@
pragma solidity 0.5.0;
contract EtherStore {
uint256 public withdrawalLimit = 1 ether;
@ -14,7 +17,8 @@ contract EtherStore {
require(_weiToWithdraw <= withdrawalLimit);
// limit the time allowed to withdraw
require(now >= lastWithdrawTime[msg.sender] + 1 weeks);
require(msg.sender.call.value(_weiToWithdraw)());
(bool success, bytes memory data) = msg.sender.call.value(_weiToWithdraw)("");
require(success);
balances[msg.sender] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = now;
}

@ -1,40 +1,43 @@
pragma solidity 0.5.0;
contract Exceptions {
uint256[8] myarray;
function assert1() {
function assert1() public pure {
uint256 i = 1;
assert(i == 0);
}
function assert2() {
function assert2() public pure {
uint256 i = 1;
assert(i > 0);
}
function assert3(uint256 input) {
function assert3(uint256 input) public pure {
assert(input != 23);
}
function requireisfine(uint256 input) {
function requireisfine(uint256 input) public pure {
require(input != 23);
}
function divisionby0(uint256 input) {
function divisionby0(uint256 input) public pure {
uint256 i = 1/input;
}
function thisisfine(uint256 input) {
function thisisfine(uint256 input) public pure {
if (input > 0) {
uint256 i = 1/input;
}
}
function arrayaccess(uint256 index) {
function arrayaccess(uint256 index) public view {
uint256 i = myarray[index];
}
function thisisalsofind(uint256 index) {
function thisisalsofind(uint256 index) public view {
if (index < 8) {
uint256 i = myarray[index];
}

@ -1,12 +1,15 @@
pragma solidity 0.5.0;
contract HashForEther {
function withdrawWinnings() {
function withdrawWinnings() public {
// Winner if the last 8 hex characters of the address are 0.
require(uint32(msg.sender) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
function _sendWinnings() public {
msg.sender.transfer(address(this).balance);
}
}

@ -1,3 +1,6 @@
pragma solidity 0.5.0;
contract Origin {
address public owner;
@ -6,7 +9,7 @@ contract Origin {
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Origin() {
constructor() public {
owner = msg.sender;
}
@ -15,9 +18,7 @@ contract Origin {
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (tx.origin != owner) {
throw;
}
require(tx.origin != owner);
_;
}
@ -26,7 +27,7 @@ contract Origin {
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner {
function transferOwnership(address newOwner) public onlyOwner {
if (newOwner != address(0)) {
owner = newOwner;
}

@ -1,13 +1,17 @@
pragma solidity 0.5.0;
contract ReturnValue {
address callee = 0xE0F7e56e62b4267062172495D7506087205A4229;
address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229;
function callnotchecked() {
callee.call();
function callnotchecked() public {
callee.call("");
}
function callchecked() {
require(callee.call());
function callchecked() public {
(bool success, bytes memory data) = callee.call("");
require(success);
}
}

@ -1,152 +1,152 @@
contract Rubixi {
//Declare variables for storage critical to contract
uint private balance = 0;
uint private collectedFees = 0;
uint private feePercent = 10;
uint private pyramidMultiplier = 300;
uint private payoutOrder = 0;
address private creator;
//Sets creator
function DynamicPyramid() {
creator = msg.sender;
}
modifier onlyowner {
if (msg.sender == creator) _;
}
struct Participant {
address etherAddress;
uint payout;
}
Participant[] private participants;
pragma solidity 0.5.0;
//Fallback function
function() payable {
init();
}
//init function run on fallback
function init() private {
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid
if (msg.value < 1 ether) {
collectedFees += msg.value;
return;
}
uint _fee = feePercent;
//50% fee rebate on any ether value of 50 or greater
if (msg.value >= 50 ether) _fee /= 2;
addPayout(_fee);
}
//Function called for valid tx to the contract
function addPayout(uint _fee) private {
//Adds new address to participant array
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100));
//These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan
if (participants.length == 10) pyramidMultiplier = 200;
else if (participants.length == 25) pyramidMultiplier = 150;
// collect fees and update contract balance
balance += (msg.value * (100 - _fee)) / 100;
collectedFees += (msg.value * _fee) / 100;
//Pays earlier participiants if balance sufficient
while (balance > participants[payoutOrder].payout) {
uint payoutToSend = participants[payoutOrder].payout;
participants[payoutOrder].etherAddress.send(payoutToSend);
balance -= participants[payoutOrder].payout;
payoutOrder += 1;
}
}
contract Rubixi {
//Declare variables for storage critical to contract
uint private balance = 0;
uint private collectedFees = 0;
uint private feePercent = 10;
uint private pyramidMultiplier = 300;
uint private payoutOrder = 0;
address payable private creator;
modifier onlyowner {
if (msg.sender == creator) _;
}
struct Participant {
address payable etherAddress;
uint payout;
}
//Fallback function
function() external payable {
init();
}
//Sets creator
function dynamicPyramid() public {
creator = msg.sender;
}
Participant[] private participants;
//Fee functions for creator
function collectAllFees() public onlyowner {
require(collectedFees == 0);
creator.transfer(collectedFees);
collectedFees = 0;
}
function collectFeesInEther(uint _amt) public onlyowner {
_amt *= 1 ether;
if (_amt > collectedFees) collectAllFees();
require(collectedFees == 0);
creator.transfer(_amt);
collectedFees -= _amt;
}
function collectPercentOfFees(uint _pcent) public onlyowner {
require(collectedFees == 0 || _pcent > 100);
uint feesToCollect = collectedFees / 100 * _pcent;
creator.transfer(feesToCollect);
collectedFees -= feesToCollect;
}
//Functions for changing variables related to the contract
function changeOwner(address payable _owner) public onlyowner {
creator = _owner;
}
function changeMultiplier(uint _mult) public onlyowner {
require(_mult > 300 || _mult < 120);
pyramidMultiplier = _mult;
}
function changeFeePercentage(uint _fee) public onlyowner {
require(_fee > 10);
feePercent = _fee;
}
//Functions to provide information to end-user using JSON interface or other interfaces
function currentMultiplier() public view returns (uint multiplier, string memory info) {
multiplier = pyramidMultiplier;
info = "This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.";
}
function currentFeePercentage() public view returns (uint fee, string memory info) {
fee = feePercent;
info = "Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)";
}
//Fee functions for creator
function collectAllFees() onlyowner {
if (collectedFees == 0) throw;
function currentPyramidBalanceApproximately() public view returns (uint pyramidBalance, string memory info) {
pyramidBalance = balance / 1 ether;
info = "All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to";
}
creator.send(collectedFees);
collectedFees = 0;
}
function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) {
balancePayout = participants[payoutOrder].payout / 1 ether;
}
function collectFeesInEther(uint _amt) onlyowner {
_amt *= 1 ether;
if (_amt > collectedFees) collectAllFees();
function feesSeperateFromBalanceApproximately() public view returns (uint fees) {
fees = collectedFees / 1 ether;
}
if (collectedFees == 0) throw;
creator.send(_amt);
collectedFees -= _amt;
}
function totalParticipants() public view returns (uint count) {
count = participants.length;
}
function collectPercentOfFees(uint _pcent) onlyowner {
if (collectedFees == 0 || _pcent > 100) throw;
function numberOfParticipantsWaitingForPayout() public view returns (uint count) {
count = participants.length - payoutOrder;
}
uint feesToCollect = collectedFees / 100 * _pcent;
creator.send(feesToCollect);
collectedFees -= feesToCollect;
function participantDetails(uint orderInPyramid) public view returns (address addr, uint payout) {
if (orderInPyramid <= participants.length) {
addr = participants[orderInPyramid].etherAddress;
payout = participants[orderInPyramid].payout / 1 ether;
}
}
//Functions for changing variables related to the contract
function changeOwner(address _owner) onlyowner {
creator = _owner;
//init function run on fallback
function init() private {
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid
if (msg.value < 1 ether) {
collectedFees += msg.value;
return;
}
function changeMultiplier(uint _mult) onlyowner {
if (_mult > 300 || _mult < 120) throw;
uint _fee = feePercent;
// 50% fee rebate on any ether value of 50 or greater
if (msg.value >= 50 ether) _fee /= 2;
pyramidMultiplier = _mult;
}
addPayout(_fee);
}
function changeFeePercentage(uint _fee) onlyowner {
if (_fee > 10) throw;
//Function called for valid tx to the contract
function addPayout(uint _fee) private {
//Adds new address to participant array
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100));
feePercent = _fee;
}
// These statements ensure a quicker payout system to
// later pyramid entrants, so the pyramid has a longer lifespan
if (participants.length == 10) pyramidMultiplier = 200;
else if (participants.length == 25) pyramidMultiplier = 150;
//Functions to provide information to end-user using JSON interface or other interfaces
function currentMultiplier() constant returns(uint multiplier, string info) {
multiplier = pyramidMultiplier;
info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.';
}
function currentFeePercentage() constant returns(uint fee, string info) {
fee = feePercent;
info = 'Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)';
}
// collect fees and update contract balance
balance += (msg.value * (100 - _fee)) / 100;
collectedFees += (msg.value * _fee) / 100;
function currentPyramidBalanceApproximately() constant returns(uint pyramidBalance, string info) {
pyramidBalance = balance / 1 ether;
info = 'All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to';
}
function nextPayoutWhenPyramidBalanceTotalsApproximately() constant returns(uint balancePayout) {
balancePayout = participants[payoutOrder].payout / 1 ether;
}
function feesSeperateFromBalanceApproximately() constant returns(uint fees) {
fees = collectedFees / 1 ether;
}
function totalParticipants() constant returns(uint count) {
count = participants.length;
}
function numberOfParticipantsWaitingForPayout() constant returns(uint count) {
count = participants.length - payoutOrder;
}
//Pays earlier participiants if balance sufficient
while (balance > participants[payoutOrder].payout) {
uint payoutToSend = participants[payoutOrder].payout;
participants[payoutOrder].etherAddress.transfer(payoutToSend);
function participantDetails(uint orderInPyramid) constant returns(address Address, uint Payout) {
if (orderInPyramid <= participants.length) {
Address = participants[orderInPyramid].etherAddress;
Payout = participants[orderInPyramid].payout / 1 ether;
}
balance -= participants[payoutOrder].payout;
payoutOrder += 1;
}
}
}

@ -1,6 +1,9 @@
pragma solidity 0.5.0;
contract Suicide {
function kill(address addr) {
function kill(address payable addr) public {
selfdestruct(addr);
}

@ -1,3 +1,6 @@
pragma solidity 0.5.0;
contract TimeLock {
mapping(address => uint) public balances;

@ -1,11 +1,12 @@
pragma solidity ^0.4.18;
pragma solidity 0.5.0;
contract Token {
mapping(address => uint) balances;
uint public totalSupply;
function Token(uint _initialSupply) {
constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
@ -16,7 +17,7 @@ contract Token {
return true;
}
function balanceOf(address _owner) public constant returns (uint balance) {
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}

@ -1,20 +1,21 @@
pragma solidity ^0.4.16;
pragma solidity 0.5.0;
contract WeakRandom {
struct Contestant {
address addr;
address payable addr;
uint gameId;
}
uint public constant prize = 2.5 ether;
uint public constant totalTickets = 50;
uint public constant pricePerTicket = prize / totalTickets;
uint public prize = 2.5 ether;
uint public totalTickets = 50;
uint public pricePerTicket = prize / totalTickets;
uint public gameId = 1;
uint public nextTicket = 0;
mapping (uint => Contestant) public contestants;
function () payable public {
function () payable external {
uint moneySent = msg.value;
while (moneySent >= pricePerTicket && nextTicket < totalTickets) {
@ -37,10 +38,10 @@ contract WeakRandom {
address seed1 = contestants[uint(block.coinbase) % totalTickets].addr;
address seed2 = contestants[uint(msg.sender) % totalTickets].addr;
uint seed3 = block.difficulty;
bytes32 randHash = keccak256(seed1, seed2, seed3);
bytes32 randHash = keccak256(abi.encode(seed1, seed2, seed3));
uint winningNumber = uint(randHash) % totalTickets;
address winningAddress = contestants[winningNumber].addr;
address payable winningAddress = contestants[winningNumber].addr;
gameId++;
nextTicket = 0;

@ -18,16 +18,16 @@ MYTHRIL_DIR = TESTS_DIR / "mythril_dir"
class BaseTestCase(TestCase):
def setUp(self):
self.changed_files = []
self.ori_mythril_dir = getattr(os.environ, "MYTHRIL_DIR", "")
self.ori_mythril_dir = os.environ.get("MYTHRIL_DIR", "")
os.environ["MYTHRIL_DIR"] = str(MYTHRIL_DIR)
shutil.copyfile(
str(MYTHRIL_DIR / "signatures.json.example"),
str(MYTHRIL_DIR / "signatures.json"),
str(MYTHRIL_DIR / "signatures.db.example"),
str(MYTHRIL_DIR / "signatures.db"),
)
def tearDown(self):
os.environ["MYTHRIL_DIR"] = self.ori_mythril_dir
os.remove(str(MYTHRIL_DIR / "signatures.json"))
os.remove(str(MYTHRIL_DIR / "signatures.db"))
def compare_files_error_message(self):
message = "Following output files are changed, compare them manually to see differences: \n"

@ -1,268 +0,0 @@
from mythril.analysis.modules.delegatecall import detector
from mythril.analysis.ops import Call, Variable, VarType
from mythril.analysis.symbolic import SymExecWrapper
from mythril.laser.ethereum.cfg import Node
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.global_state import GlobalState
import pytest
from unittest.mock import MagicMock, patch
import pytest_mock
from mythril.disassembler.disassembly import Disassembly
def test_concrete_call():
# arrange
address = "0x10"
active_account = Account(address)
active_account.code = Disassembly("00")
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None)
state.mstate.memory = ["placeholder", "calldata_bling_0"]
node = Node("example")
node.contract_name = "the contract name"
node.function_name = "the function name"
to = Variable(1, VarType.CONCRETE)
meminstart = Variable(1, VarType.CONCRETE)
call = Call(node, state, None, None, to, None)
# act
issues = detector._concrete_call(call, state, address, meminstart)
# assert
issue = issues[0]
assert issue.address == address
assert issue.contract == node.contract_name
assert issue.function == node.function_name
assert issue.title == "Call data forwarded with delegatecall()"
assert issue.type == "Informational"
assert (
issue.description
== "This contract forwards its call data via DELEGATECALL in its fallback function."
" This means that any function in the called contract can be executed."
" Note that the callee contract will have access to the storage of the "
"calling contract.\nDELEGATECALL target: 0x1"
)
def test_concrete_call_symbolic_to():
# arrange
address = "0x10"
active_account = Account(address)
active_account.code = Disassembly("00")
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None)
state.mstate.memory = ["placeholder", "calldata_bling_0"]
node = Node("example")
node.contract_name = "the contract name"
node.function_name = "the function name"
to = Variable("calldata_3", VarType.SYMBOLIC)
meminstart = Variable(1, VarType.CONCRETE)
call = Call(node, state, None, None, to, None)
# act
issues = detector._concrete_call(call, state, address, meminstart)
# assert
issue = issues[0]
assert issue.address == address
assert issue.contract == node.contract_name
assert issue.function == node.function_name
assert issue.title == "Call data forwarded with delegatecall()"
assert issue.type == "Informational"
assert issue.description == (
"This contract forwards its call data via DELEGATECALL in its fallback function."
" This means that any function in the called contract can be executed."
" Note that the callee contract will have access to the storage of the "
"calling contract.\nDELEGATECALL target: calldata_3"
)
def test_concrete_call_not_calldata():
# arrange
state = GlobalState(None, None, None)
state.mstate.memory = ["placeholder", "not_calldata"]
meminstart = Variable(1, VarType.CONCRETE)
# act
issues = detector._concrete_call(None, state, None, meminstart)
# assert
assert issues == []
def test_symbolic_call_storage_to(mocker):
# arrange
address = "0x10"
active_account = Account(address)
active_account.code = Disassembly("00")
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None)
state.mstate.memory = ["placeholder", "calldata_bling_0"]
node = Node("example")
node.contract_name = "the contract name"
node.function_name = "the function name"
to = Variable("storage_1", VarType.SYMBOLIC)
call = Call(node, state, None, "Type: ", to, None)
mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None)
statespace = SymExecWrapper(1)
mocker.patch.object(statespace, "find_storage_write")
statespace.find_storage_write.return_value = "Function name"
# act
issues = detector._symbolic_call(call, state, address, statespace)
# assert
issue = issues[0]
assert issue.address == address
assert issue.contract == node.contract_name
assert issue.function == node.function_name
assert issue.title == "Type: to a user-supplied address"
assert issue.type == "Informational"
assert issue.description == (
"This contract delegates execution to a contract address in storage slot 1."
" This storage slot can be written to by calling the function `Function name`."
" Be aware that the called contract gets unrestricted access to this contract's state."
)
def test_symbolic_call_calldata_to(mocker):
# arrange
address = "0x10"
active_account = Account(address)
active_account.code = Disassembly("00")
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, None)
state.mstate.memory = ["placeholder", "calldata_bling_0"]
node = Node("example")
node.contract_name = "the contract name"
node.function_name = "the function name"
to = Variable("calldata", VarType.SYMBOLIC)
call = Call(node, state, None, "Type: ", to, None)
mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None)
statespace = SymExecWrapper(1)
mocker.patch.object(statespace, "find_storage_write")
statespace.find_storage_write.return_value = "Function name"
# act
issues = detector._symbolic_call(call, state, address, statespace)
# assert
issue = issues[0]
assert issue.address == address
assert issue.contract == node.contract_name
assert issue.function == node.function_name
assert issue.title == "Type: to a user-supplied address"
assert issue.type == "Informational"
assert issue.description == (
"This contract delegates execution to a contract address obtained from calldata."
" Be aware that the called contract gets unrestricted access to this contract's state."
)
@patch("mythril.laser.ethereum.state.global_state.GlobalState.get_current_instruction")
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call")
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call")
def test_delegate_call(sym_mock, concrete_mock, curr_instruction):
# arrange
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call")
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call")
sym_mock.return_value = []
concrete_mock.return_value = []
curr_instruction.return_value = {"address": "0x10"}
active_account = Account("0x10")
active_account.code = Disassembly("00")
environment = Environment(active_account, None, None, None, None, None)
state = GlobalState(None, environment, Node)
state.mstate.memory = ["placeholder", "calldata_bling_0"]
state.mstate.stack = [1, 2, 3]
assert state.get_current_instruction() == {"address": "0x10"}
node = Node("example")
node.contract_name = "the contract name"
node.function_name = "fallback"
to = Variable("storage_1", VarType.SYMBOLIC)
call = Call(node, state, None, "DELEGATECALL", to, None)
statespace = MagicMock()
statespace.calls = [call]
# act
detector.execute(statespace)
# assert
assert concrete_mock.call_count == 1
assert sym_mock.call_count == 1
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call")
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call")
def test_delegate_call_not_delegate(sym_mock, concrete_mock):
# arrange
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call")
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call")
sym_mock.return_value = []
concrete_mock.return_value = []
node = Node("example")
node.function_name = "fallback"
to = Variable("storage_1", VarType.SYMBOLIC)
call = Call(node, None, None, "NOT_DELEGATECALL", to, None)
statespace = MagicMock()
statespace.calls = [call]
# act
issues = detector.execute(statespace)
# assert
assert issues == []
assert concrete_mock.call_count == 0
assert sym_mock.call_count == 0
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call")
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call")
def test_delegate_call_not_fallback(sym_mock, concrete_mock):
# arrange
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call")
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call")
sym_mock.return_value = []
concrete_mock.return_value = []
node = Node("example")
node.function_name = "not_fallback"
to = Variable("storage_1", VarType.SYMBOLIC)
call = Call(node, None, None, "DELEGATECALL", to, None)
statespace = MagicMock()
statespace.calls = [call]
# act
issues = detector.execute(statespace)
# assert
assert issues == []
assert concrete_mock.call_count == 0
assert sym_mock.call_count == 0

@ -1,5 +1,5 @@
from subprocess import check_output
from tests import *
from tests import BaseTestCase, TESTDATA, PROJECT_DIR, TESTS_DIR
MYTH = str(PROJECT_DIR / "myth")
@ -10,23 +10,23 @@ def output_of(command):
class CommandLineToolTestCase(BaseTestCase):
def test_disassemble_code_correctly(self):
command = "python3 {} MYTH -d --bin-runtime -c 0x5050".format(MYTH)
self.assertEqual("0 POP\n1 POP\n", output_of(command))
command = "python3 {} MYTH -d --bin-runtime -c 0x5050 --solv 0.5.0".format(MYTH)
self.assertIn("0 POP\n1 POP\n", output_of(command))
def test_disassemble_solidity_file_correctly(self):
solidity_file = str(TESTDATA / "input_contracts" / "metacoin.sol")
command = "python3 {} -d {}".format(MYTH, solidity_file)
command = "python3 {} -d {} --solv 0.5.0".format(MYTH, solidity_file)
self.assertIn("2 PUSH1 0x40\n4 MSTORE", output_of(command))
def test_hash_a_function_correctly(self):
command = "python3 {} --hash 'setOwner(address)'".format(MYTH)
self.assertEqual("0x13af4035\n", output_of(command))
command = "python3 {} --solv 0.5.0 --hash 'setOwner(address)'".format(MYTH)
self.assertIn("0x13af4035\n", output_of(command))
class TruffleTestCase(BaseTestCase):
def test_analysis_truffle_project(self):
truffle_project_root = str(TESTS_DIR / "truffle_project")
command = "cd {}; truffle compile; python3 {} --truffle -t 1".format(
command = "cd {}; truffle compile; python3 {} --truffle -t 2".format(
truffle_project_root, MYTH
)
self.assertIn("=== Ether thief ====", output_of(command))

@ -12,7 +12,7 @@ def test_get_function_info(mocker):
# Arrange
global instruction_list
signature_database_mock = SignatureDb()
signature_database_mock = SignatureDB()
mocker.patch.object(signature_database_mock, "get")
signature_database_mock.get.return_value = ["function_name"]
@ -31,7 +31,7 @@ def test_get_function_info_multiple_names(mocker):
# Arrange
global instruction_list
signature_database_mock = SignatureDb()
signature_database_mock = SignatureDB()
mocker.patch.object(signature_database_mock, "get")
signature_database_mock.get.return_value = ["function_name", "another_name"]
@ -48,7 +48,7 @@ def test_get_function_info_no_names(mocker):
# Arrange
global instruction_list
signature_database_mock = SignatureDb()
signature_database_mock = SignatureDB()
mocker.patch.object(signature_database_mock, "get")
signature_database_mock.get.return_value = []

@ -1,5 +1,5 @@
from mythril.disassembler.disassembly import Disassembly
from mythril.ether import util
from mythril.ethereum import util
from tests import *

@ -1,41 +1,42 @@
import unittest
from mythril.ether.ethcontract import ETHContract
from mythril.ethereum.evmcontract import EVMContract
from tests import BaseTestCase
class ETHContractTestCase(unittest.TestCase):
class EVMContractTestCase(BaseTestCase):
def setUp(self):
super().setUp()
self.code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029"
self.creation_code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029"
class Getinstruction_listTestCase(ETHContractTestCase):
class Getinstruction_listTestCase(EVMContractTestCase):
def runTest(self):
contract = ETHContract(self.code, self.creation_code)
contract = EVMContract(self.code, self.creation_code)
disassembly = contract.disassembly
self.assertEqual(
len(disassembly.instruction_list),
53,
"Error disassembling code using ETHContract.get_instruction_list()",
"Error disassembling code using EVMContract.get_instruction_list()",
)
class GetEASMTestCase(ETHContractTestCase):
class GetEASMTestCase(EVMContractTestCase):
def runTest(self):
contract = ETHContract(self.code)
contract = EVMContract(self.code)
instruction_list = contract.get_easm()
self.assertTrue(
"PUSH1 0x60" in instruction_list,
"Error obtaining EASM code through ETHContract.get_easm()",
"Error obtaining EASM code through EVMContract.get_easm()",
)
class MatchesExpressionTestCase(ETHContractTestCase):
class MatchesExpressionTestCase(EVMContractTestCase):
def runTest(self):
contract = ETHContract(self.code)
contract = EVMContract(self.code)
self.assertTrue(
contract.matches_expression("code#PUSH1# or code#PUSH1#"),

@ -1,14 +1,18 @@
from mythril.analysis.callgraph import generate_graph
from mythril.analysis.symbolic import SymExecWrapper
from mythril.ether import util
from mythril.ether.soliditycontract import ETHContract
from tests import *
from mythril.ethereum import util
from mythril.solidity.soliditycontract import EVMContract
from tests import (
BaseTestCase,
TESTDATA_INPUTS,
TESTDATA_OUTPUTS_EXPECTED,
TESTDATA_OUTPUTS_CURRENT,
)
import re
class GraphTest(BaseTestCase):
def test_generate_graph(self):
for input_file in TESTDATA_INPUTS.iterdir():
output_expected = TESTDATA_OUTPUTS_EXPECTED / (
input_file.name + ".graph.html"
@ -17,7 +21,7 @@ class GraphTest(BaseTestCase):
input_file.name + ".graph.html"
)
contract = ETHContract(input_file.read_text())
contract = EVMContract(input_file.read_text())
sym = SymExecWrapper(
contract,

@ -7,6 +7,7 @@ from datetime import datetime
import binascii
import json
import os
from pathlib import Path
import pytest
from z3 import ExprRef, simplify

@ -1,6 +1,6 @@
import pytest
from mythril.laser.ethereum.state.calldata import Calldata
from z3 import Solver, simplify
from mythril.laser.ethereum.state.calldata import ConcreteCalldata, SymbolicCalldata
from z3 import Solver, simplify, BitVec, sat, unsat
from z3.z3types import Z3Exception
from mock import MagicMock
@ -13,21 +13,11 @@ uninitialized_test_data = [
@pytest.mark.parametrize("starting_calldata", uninitialized_test_data)
def test_concrete_calldata_uninitialized_index(starting_calldata):
# Arrange
calldata = Calldata(0, starting_calldata)
solver = Solver()
calldata = ConcreteCalldata(0, starting_calldata)
# Act
value, constraint1 = calldata[100]
value2, constraint2 = calldata.get_word_at(200)
solver.add(constraint1)
solver.add(constraint2)
solver.check()
model = solver.model()
value = model.eval(value)
value2 = model.eval(value2)
value = calldata[100]
value2 = calldata.get_word_at(200)
# Assert
assert value == 0
@ -36,73 +26,65 @@ def test_concrete_calldata_uninitialized_index(starting_calldata):
def test_concrete_calldata_calldatasize():
# Arrange
calldata = Calldata(0, [1, 4, 7, 3, 7, 2, 9])
calldata = ConcreteCalldata(0, [1, 4, 7, 3, 7, 2, 9])
solver = Solver()
# Act
solver.check()
model = solver.model()
result = model.eval(calldata.calldatasize)
# Assert
assert result == 7
def test_symbolic_calldata_constrain_index():
def test_concrete_calldata_constrain_index():
# Arrange
calldata = Calldata(0)
calldata = ConcreteCalldata(0, [1, 4, 7, 3, 7, 2, 9])
solver = Solver()
# Act
value, calldata_constraints = calldata[100]
constraint = value == 50
solver.add([constraint] + calldata_constraints)
solver.check()
model = solver.model()
value = calldata[2]
constraint = value == 3
value = model.eval(value)
calldatasize = model.eval(calldata.calldatasize)
solver.add([constraint])
result = solver.check()
# Assert
assert value == 50
assert simplify(calldatasize >= 100)
assert str(result) == "unsat"
def test_concrete_calldata_constrain_index():
def test_symbolic_calldata_constrain_index():
# Arrange
calldata = Calldata(0, [1, 4, 7, 3, 7, 2, 9])
calldata = SymbolicCalldata(0)
solver = Solver()
# Act
value, calldata_constraints = calldata[2]
constraint = value == 3
value = calldata[51]
constraints = [value == 1, calldata.calldatasize == 50]
solver.add(constraints)
solver.add([constraint] + calldata_constraints)
result = solver.check()
# Assert
assert str(result) == "unsat"
def test_concrete_calldata_constrain_index():
# Arrange
calldata = Calldata(0)
mstate = MagicMock()
mstate.constraints = []
solver = Solver()
def test_symbolic_calldata_equal_indices():
calldata = SymbolicCalldata(0)
# Act
constraints = []
value, calldata_constraints = calldata[51]
constraints.append(value == 1)
constraints.append(calldata.calldatasize == 50)
index_a = BitVec("index_a", 256)
index_b = BitVec("index_b", 256)
solver.add(constraints + calldata_constraints)
# Act
a = calldata[index_a]
b = calldata[index_b]
result = solver.check()
s = Solver()
s.append(index_a == index_b)
s.append(a != b)
# Assert
assert str(result) == "unsat"
assert unsat == s.check()

@ -1,16 +1,20 @@
from mythril.mythril import Mythril
from mythril.laser.ethereum.transaction import execute_contract_creation
from mythril.ether import util
from mythril.ethereum import util
import mythril.laser.ethereum.svm as svm
from mythril.disassembler.disassembly import Disassembly
from datetime import datetime
from mythril.ether.soliditycontract import SolidityContract
from mythril.solidity.soliditycontract import SolidityContract
import tests
from mythril.analysis.security import fire_lasers
from mythril.analysis.symbolic import SymExecWrapper
def test_create():
contract = SolidityContract(str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"))
contract = SolidityContract(
str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"),
solc_binary=Mythril._init_solc_binary("0.5.0"),
)
laser_evm = svm.LaserEVM({})
@ -31,7 +35,10 @@ def test_create():
def test_sym_exec():
contract = SolidityContract(str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"))
contract = SolidityContract(
str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"),
solc_binary=Mythril._init_solc_binary("0.5.0"),
)
sym = SymExecWrapper(
contract, address=(util.get_indexed_address(0)), strategy="dfs"

@ -0,0 +1,4 @@
[defaults]
leveldb_dir = /Users/bernhardmueller/Library/Ethereum/geth/chaindata
dynamic_loading = infura

File diff suppressed because it is too large Load Diff

@ -1,52 +1,31 @@
from mythril.ether.soliditycontract import SolidityContract
from mythril.solidity.soliditycontract import SolidityContract
from mythril.mythril import Mythril
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 import svm
from tests import *
from tests import BaseTestCase
SHA256_TEST = [(0, False) for _ in range(4)]
RIPEMD160_TEST = [(0, False) for _ in range(2)]
ECRECOVER_TEST = [(0, False) for _ in range(2)]
IDENTITY_TEST = [(0, False) for _ in range(2)]
SHA256_TEST = [(0, False) for _ in range(6)]
# These are Random numbers to check whether the 'if condition' is entered or not
# (True means entered)
SHA256_TEST[0] = (hex(5555555555555555), True)
SHA256_TEST[1] = (hex(323232325445454546), True)
SHA256_TEST[2] = (hex(34756834765834658), True)
SHA256_TEST[3] = (hex(8756476956956795876987), True)
RIPEMD160_TEST = [(0, False) for _ in range(6)]
RIPEMD160_TEST[0] = (hex(999999999999999999993), True)
RIPEMD160_TEST[1] = (hex(1111111111112), True)
ECRECOVER_TEST = [(0, False) for _ in range(9)]
ECRECOVER_TEST[0] = (hex(674837568743979857398564869), True)
ECRECOVER_TEST[1] = (hex(3487683476979311), False)
IDENTITY_TEST = [(0, False) for _ in range(4)]
SHA256_TEST[0] = (
5555555555555555,
True,
) # These are Random numbers to check whether the 'if condition' is entered or not(True means entered)
SHA256_TEST[1] = (323232325445454546, True)
SHA256_TEST[2] = (34756834765834658, False)
SHA256_TEST[3] = (8756476956956795876987, True)
SHA256_TEST[4] = (5763467587689578369, True)
SHA256_TEST[5] = (948365957658767467857, False)
RIPEMD160_TEST[0] = (1242435356364, True)
RIPEMD160_TEST[1] = (6732648654386435, True)
RIPEMD160_TEST[2] = (97457657536546465, False)
RIPEMD160_TEST[3] = (56436346436456546, True)
RIPEMD160_TEST[4] = (999999999999999999993, True)
RIPEMD160_TEST[5] = (1111111111112, False)
ECRECOVER_TEST[0] = (786428768768632537676, True)
ECRECOVER_TEST[1] = (4897983476979346779638, False)
ECRECOVER_TEST[2] = (674837568743979857398564869, True)
ECRECOVER_TEST[3] = (3487683476979311, False)
ECRECOVER_TEST[4] = (853729594875984769847369, True)
ECRECOVER_TEST[5] = (83579382475972439587, False)
ECRECOVER_TEST[6] = (8437589437695876985769, True)
ECRECOVER_TEST[7] = (9486794873598347697596, False)
ECRECOVER_TEST[8] = (346934876983476, True)
IDENTITY_TEST[0] = (87426857369875698, True)
IDENTITY_TEST[1] = (476934798798347, False)
IDENTITY_TEST[2] = (7346948379483769, True)
IDENTITY_TEST[3] = (83269476937987, False)
IDENTITY_TEST[0] = (hex(87426857369875698), True)
IDENTITY_TEST[1] = (hex(476934798798347), False)
def _all_info(laser):
@ -98,17 +77,20 @@ def _all_info(laser):
def _test_natives(laser_info, test_list, test_name):
success = 0
for i, j in test_list:
if (str(i) in laser_info) == j:
if (str(i) in laser_info or str(int(i, 16)) in laser_info) == j:
success += 1
else:
print("Failed: " + str(i) + " " + str(j))
print("Failed:", str(int(i, 16)), str(j))
assert success == len(test_list)
class NativeTests(BaseTestCase):
@staticmethod
def runTest():
disassembly = SolidityContract("./tests/native_tests.sol").disassembly
disassembly = SolidityContract(
"./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.5.0")
).disassembly
account = Account("0x0000000000000000000000000000000000000000", disassembly)
accounts = {account.address: account}
@ -116,8 +98,8 @@ class NativeTests(BaseTestCase):
laser.sym_exec(account.address)
laser_info = str(_all_info(laser))
print("\n")
print(laser_info)
_test_natives(laser_info, SHA256_TEST, "SHA256")
_test_natives(laser_info, RIPEMD160_TEST, "RIPEMD160")
_test_natives(laser_info, ECRECOVER_TEST, "ECRECOVER")

@ -1,147 +1,90 @@
pragma solidity ^0.4.17;
pragma solidity 0.5.0;
contract Caller {
address public fixed_address; //Just some useless variables
address public stored_address;
//Just some useless variables
address public fixedAddress;
address public storedAddress;
uint256 statevar; //useless( but good for testing as they contribute as decoys)
bytes32 far;
//useless (but good for testing as they contribute as decoys)
uint256 private statevar;
bytes32 private far;
function Caller(address addr) {
fixed_address = addr;
constructor (address addr) public {
fixedAddress = addr;
}
function thisisfine() public { //some typical function as a decoy
fixed_address.call();
//some typical function as a decoy
function thisisfine() public {
(bool success, bytes memory mem) = fixedAddress.call("");
}
function sha256_test1() public {
function sha256Test1() public returns (uint256) {
uint256 i;
if(sha256('ab','c') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True
if (sha256(abi.encodePacked("ab", "c")) == sha256("abc")) {
// True
i = 5555555555555555;
}
if(sha256('abc') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True
} else {
// False
i = 323232325445454546;
}
return i;
}
function sha256_test2() public {
function sha256Test2() public returns (uint256) {
uint256 i;
if(sha256('abd') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad) { //False
if (sha256("abd") == sha256(abi.encodePacked("ab", "d"))) {
// True
i = 34756834765834658;
}
if(sha256('ab','d') == 0xa52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9) { //True
} else {
// False
i = 8756476956956795876987;
}
}
function sha256_test3() public {
uint256 i;
if(sha256('') == 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855) { //True
i = 5763467587689578369;
}
if(sha256('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdhhfdhhhhhh') == 0xe4ebd771f821e3277b77dcc39e94fe7172a5c9c8c12f8885c2d5513385a0a8b8) { //False
i = 948365957658767467857;
}
return i;
}
function ripemd_test1() public {
uint256 i;
if(ripemd160('ab','c') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True
i = 1242435356364;
}
if(ripemd160('abc') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True
i = 6732648654386435;
}
}
function ripemd_test2() public {
uint256 i;
if(ripemd160('abd') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc) { //False
i = 97457657536546465;
}
if(ripemd160('ab','d') == 0xb0a79cc77e333ea11974e105cd051d33836928b0) { //True
i = 56436346436456546;
}
}
function ripemd_test3() public {
uint256 i;
if(ripemd160('') == 0x9c1185a5c5e9fc54612808977ee8f548b2258d31) { //True
i = 999999999999999999993;
}
if(ripemd160('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh') == 0x2d1b88a5daa5d138eb7bb14ee320010937f0ebe7) { //False
i = 1111111111112;
}
}
function ripemdTest() public returns (uint256) {
uint256 i;
bytes20 v1 = ripemd160("");
bytes20 v2 = ripemd160("hhhhh");
function ecrecover_test1() public {
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8;
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(prefix, foobar);
if (v1 != v2) {
// True
i = 999999999999999999993;
} else {
// False
i = 1111111111112;
}
return i;
}
function ecrecoverTest() public returns (uint256) {
bytes32 foobar1 = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8;
bytes32 foobar2 = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e;
uint8 v = 28;
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608;
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada;
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8a) { //True
uint256 bignum = 786428768768632537676;
}
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False
uint256 small = 4897983476979346779638;
}
foobar = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e;
if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //True
uint256 dk = 674837568743979857398564869;
}
foobar = 0x38d18acb67d25c7bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; //not same as above, minor change(7bb instead of 8bb)
if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //False
uint256 pk = 3487683476979311;
uint256 i;
address addr1 = ecrecover(keccak256(abi.encodePacked(foobar1)), v, r, s);
address addr2 = ecrecover(keccak256(abi.encodePacked(foobar1, foobar2)), v, r, s);
if (addr1 != addr2) {
// True
i = 674837568743979857398564869;
} else {
// False
i = 3487683476979311;
}
return i;
}
function ecrecover_test2() public {
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8;
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(prefix, foobar);
uint8 v = 26;
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608;
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada;
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True
uint256 bignum = 853729594875984769847369;
}
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False
uint256 small = 83579382475972439587;
}
}
function ecrecover_test3() public {
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8;
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(prefix, foobar);
uint8 v = 29;
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608;
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada;
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True
uint256 bignum = 8437589437695876985769;
}
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False
uint256 small = 9486794873598347697596;
}
//identity is invoked here in compiler and not below
function needIdentityInvoke(uint sea) public returns (uint) {
return sea;
}
function ecrecover_test4() public {
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8;
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 prefixedHash = keccak256(prefix, foobar);
uint8 v = 27;
bytes32 r = 0xfffffffffffffffffffffffffffffffffaaedce6af48a03bbfd25e8cd0364141; //greater than the max limit
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada;
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True
uint256 bignum = 346934876983476;
}
}
function need_identity_invoke(uint sea) returns (uint) {
return sea; //identity is invoked here in compiler and not below
}
function identity_function(int input) public returns(int out) {
assembly{
function identityFunction(int input) public returns(int out) {
assembly {
let x := mload(0x40)
mstore(x, input)
@ -150,17 +93,16 @@ contract Caller {
mstore(0x40, x)
}
}
function identity_test1() public{
if(identity_function(100)==100) //True
uint256 smallnum = 87426857369875698;
if(identity_function(200)==100) //False
uint256 bignum = 476934798798347;
}
function identity_test2() public{
if(identity_function(12345678)==12345678) //True
uint256 smallnum = 7346948379483769;
if(identity_function(74648796976)==4685987) //False
uint256 bignum = 83269476937987;
}
function identityTest1() public returns (uint256) {
uint256 i;
if (identityFunction(100) == 100) {
// True
i = 87426857369875698;
} else {
// False
i = 476934798798347;
}
return i;
}
}

@ -1,10 +1,9 @@
from mythril.analysis.report import Report
from mythril.analysis.security import fire_lasers
from mythril.analysis.security import fire_lasers, reset_callback_modules
from mythril.analysis.symbolic import SymExecWrapper
from mythril.ether import util
from mythril.ether.soliditycontract import ETHContract
from mythril.ethereum import util
from mythril.solidity.soliditycontract import EVMContract
from multiprocessing import Pool, cpu_count
import datetime
import pytest
import json
from tests import *
@ -23,7 +22,7 @@ def _fix_debug_data(json_str):
def _generate_report(input_file):
contract = ETHContract(input_file.read_text(), enable_online_lookup=False)
contract = EVMContract(input_file.read_text(), enable_online_lookup=False)
sym = SymExecWrapper(
contract,
address=(util.get_indexed_address(0)),
@ -43,6 +42,7 @@ def _generate_report(input_file):
@pytest.fixture(scope="module")
def reports():
""" Fixture that analyses all reports"""
reset_callback_modules()
pool = Pool(cpu_count())
input_files = sorted(
[f for f in TESTDATA_INPUTS.iterdir() if f.name != "environments.sol.o"]

@ -1,9 +1,10 @@
from unittest import TestCase
from tests import BaseTestCase
from mythril.ethereum.interface.rpc.client import EthJsonRpc
class RpcTest(TestCase):
class RpcTest(BaseTestCase):
client = None
def setUp(self):

@ -1,6 +1,7 @@
from pathlib import Path
from mythril.ether.soliditycontract import SolidityContract
from mythril.mythril import Mythril
from mythril.solidity.soliditycontract import SolidityContract
from tests import BaseTestCase
TEST_FILES = Path(__file__).parent / "testdata/input_contracts"
@ -9,7 +10,9 @@ TEST_FILES = Path(__file__).parent / "testdata/input_contracts"
class SolidityContractTest(BaseTestCase):
def test_get_source_info_without_name_gets_latest_contract_info(self):
input_file = TEST_FILES / "multi_contracts.sol"
contract = SolidityContract(str(input_file))
contract = SolidityContract(
str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0")
)
code_info = contract.get_source_info(142)
@ -19,7 +22,11 @@ class SolidityContractTest(BaseTestCase):
def test_get_source_info_with_contract_name_specified(self):
input_file = TEST_FILES / "multi_contracts.sol"
contract = SolidityContract(str(input_file), name="Transfer1")
contract = SolidityContract(
str(input_file),
name="Transfer1",
solc_binary=Mythril._init_solc_binary("0.5.0"),
)
code_info = contract.get_source_info(142)
@ -29,10 +36,14 @@ class SolidityContractTest(BaseTestCase):
def test_get_source_info_with_contract_name_specified_constructor(self):
input_file = TEST_FILES / "constructor_assert.sol"
contract = SolidityContract(str(input_file), name="AssertFail")
contract = SolidityContract(
str(input_file),
name="AssertFail",
solc_binary=Mythril._init_solc_binary("0.5.0"),
)
code_info = contract.get_source_info(62, constructor=True)
code_info = contract.get_source_info(70, constructor=True)
self.assertEqual(code_info.filename, str(input_file))
self.assertEqual(code_info.lineno, 6)
self.assertEqual(code_info.code, "assert(var1>0)")
self.assertEqual(code_info.code, "assert(var1 > 0)")

@ -2,14 +2,21 @@ import json
from mythril.analysis.security import get_detection_module_hooks
from mythril.analysis.symbolic import SymExecWrapper
from mythril.analysis.callgraph import generate_graph
from mythril.ether.ethcontract import ETHContract
from mythril.ether.soliditycontract import SolidityContract
from mythril.ethereum.evmcontract import EVMContract
from mythril.solidity.soliditycontract import SolidityContract
from mythril.mythril import Mythril
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 import svm
from tests import *
from tests import (
BaseTestCase,
TESTDATA_INPUTS_CONTRACTS,
TESTDATA_OUTPUTS_EXPECTED_LASER_RESULT,
TESTDATA_OUTPUTS_CURRENT_LASER_RESULT,
)
class LaserEncoder(json.JSONEncoder):
@ -81,7 +88,9 @@ class SVMTestCase(BaseTestCase):
input_file.name + ".json"
)
disassembly = SolidityContract(str(input_file)).disassembly
disassembly = SolidityContract(
str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0")
).disassembly
account = Account("0x0000000000000000000000000000000000000000", disassembly)
accounts = {account.address: account}
@ -105,7 +114,7 @@ class SVMTestCase(BaseTestCase):
code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029"
contract = ETHContract(code)
contract = EVMContract(code)
sym = SymExecWrapper(contract, "0xd0a6E6C543bC68Db5db3A191B171A77407Ff7ccf")
html = generate_graph(sym)

@ -1,6 +1,6 @@
# compile test contracts
from pathlib import Path
from mythril.ether.soliditycontract import SolidityContract
from mythril.solidity.soliditycontract import SolidityContract
# Recompiles all the to be tested contracts
root = Path(__file__).parent

@ -1,4 +1,4 @@
pragma solidity ^0.4.17;
pragma solidity 0.5.0;
contract Caller {
@ -8,28 +8,29 @@ contract Caller {
uint256 statevar;
function Caller(address addr) {
fixed_address = addr;
constructor(address addr) public {
fixed_address = address(0x552254CbAaF32613C6c0450CF19524594eF84044);
}
function thisisfine() public {
fixed_address.call();
fixed_address.call("");
}
function reentrancy() public {
fixed_address.call();
fixed_address.call("");
statevar = 0;
}
function calluseraddress(address addr) {
addr.call();
function calluseraddress(address addr) public {
addr.call("");
}
function callstoredaddress() {
stored_address.call();
function callstoredaddress() public {
stored_address.call("");
statevar = 0;
}
function setstoredaddress(address addr) {
function setstoredaddress(address addr) public {
stored_address = addr;
}

@ -1,8 +1,8 @@
pragma solidity ^0.4.24;
pragma solidity 0.5.0;
contract AssertFail {
constructor(uint8 var1){
assert(var1>0);
}
contract AssertFail {
constructor(uint8 var1) public {
assert(var1 > 0);
}
}

@ -1,11 +1,11 @@
pragma solidity ^0.4.16;
pragma solidity 0.5.0;
contract IntegerOverflow2 {
uint256 public count = 7;
mapping(address => uint256) balances;
function batchTransfer(address[] _receivers, uint256 _value) public returns(bool){
function batchTransfer(address[] memory _receivers, uint256 _value) public returns(bool){
uint cnt = _receivers.length;
uint256 amount = uint256(cnt) * _value;

@ -1,3 +1,6 @@
pragma solidity 0.5.0;
contract Crowdfunding {
mapping(address => uint) public balances;
@ -10,12 +13,12 @@ contract Crowdfunding {
_;
}
function crowdfunding() {
function crowdfunding() public {
owner = msg.sender;
}
function withdrawfunds() onlyOwner {
msg.sender.transfer(this.balance);
function withdrawfunds() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
function invest() public payable {
@ -24,7 +27,7 @@ contract Crowdfunding {
balances[msg.sender] += msg.value;
}
function getBalance() public constant returns (uint) {
function getBalance() public view returns (uint) {
return balances[msg.sender];
}

@ -1,40 +1,43 @@
pragma solidity 0.5.0;
contract Exceptions {
uint256[8] myarray;
function assert1() {
function assert1() public pure {
uint256 i = 1;
assert(i == 0);
}
function assert2() {
function assert2() public pure {
uint256 i = 1;
assert(i > 0);
}
function assert3(uint256 input) {
function assert3(uint256 input) public pure {
assert(input != 23);
}
function requireisfine(uint256 input) {
function requireisfine(uint256 input) public pure {
require(input != 23);
}
function divisionby0(uint256 input) {
function divisionby0(uint256 input) public pure {
uint256 i = 1/input;
}
function thisisfine(uint256 input) {
function thisisfine(uint256 input) public pure {
if (input > 0) {
uint256 i = 1/input;
}
}
function arrayaccess(uint256 index) {
function arrayaccess(uint256 index) public view {
uint256 i = myarray[index];
}
function thisisalsofind(uint256 index) {
function thisisalsofind(uint256 index) public view {
if (index < 8) {
uint256 i = myarray[index];
}

@ -1,16 +1,19 @@
pragma solidity 0.5.0;
contract D {
uint public n;
address public sender;
function callSetN(address _e, uint _n) {
_e.call(bytes4(sha3("setN(uint256)")), _n);
function callSetN(address _e, uint _n) public {
_e.call(abi.encode(bytes4(keccak256("setN(uint256)")), _n));
}
function callcodeSetN(address _e, uint _n) {
_e.callcode(bytes4(sha3("setN(uint256)")), _n);
function callcodeSetN(address _e, uint _n) public view {
_e.staticcall(abi.encode(bytes4(keccak256("setN(uint256)")), _n));
}
function delegatecallSetN(address _e, uint _n) {
_e.delegatecall(bytes4(sha3("setN(uint256)")), _n);
function delegatecallSetN(address _e, uint _n) public {
_e.delegatecall(abi.encode(bytes4(keccak256("setN(uint256)")), _n));
}
}

@ -1,8 +1,9 @@
pragma solidity ^0.4.17;
pragma solidity 0.5.0;
contract MetaCoin {
mapping (address => uint) public balances;
function MetaCoin() public {
constructor() public {
balances[msg.sender] = 10000;
}

@ -1,17 +1,16 @@
pragma solidity ^0.4.17;
pragma solidity 0.5.0;
contract Transfer1 {
function transfer() {
msg.sender.transfer(1 ether);
}
contract Transfer1 {
function transfer() public {
msg.sender.transfer(1 ether);
}
}
contract Transfer2 {
function transfer() {
msg.sender.transfer(2 ether);
}
contract Transfer2 {
function transfer() public {
msg.sender.transfer(2 ether);
}
}

@ -1,6 +1,8 @@
pragma solidity ^0.4.22;
pragma solidity 0.5.0;
contract nonAscii {
function renderNonAscii () public pure returns (string) {
function renderNonAscii () public pure returns (string memory) {
return "Хэллоу Ворлд";
}
}

@ -1,3 +1,6 @@
pragma solidity 0.5.0;
contract Origin {
address public owner;
@ -6,7 +9,7 @@ contract Origin {
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Origin() {
constructor() public {
owner = msg.sender;
}
@ -15,9 +18,7 @@ contract Origin {
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (tx.origin != owner) {
throw;
}
require(tx.origin != owner);
_;
}
@ -26,7 +27,7 @@ contract Origin {
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner {
function transferOwnership(address newOwner) public onlyOwner {
if (newOwner != address(0)) {
owner = newOwner;
}

@ -1,20 +1,23 @@
pragma solidity 0.5.0;
contract Over {
mapping(address => uint) balances;
uint public totalSupply;
function Token(uint _initialSupply) {
constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
function sendeth(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0);
// require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}
function balanceOf(address _owner) public constant returns (uint balance) {
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}

@ -1,13 +1,17 @@
pragma solidity 0.5.0;
contract ReturnValue {
address callee = 0xE0F7e56e62b4267062172495D7506087205A4229;
address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229;
function callnotchecked() {
callee.call();
function callnotchecked() public {
callee.call("");
}
function callchecked() {
require(callee.call());
function callchecked() public {
(bool success, bytes memory data) = callee.call("");
require(success);
}
}

@ -1,152 +1,152 @@
contract Rubixi {
//Declare variables for storage critical to contract
uint private balance = 0;
uint private collectedFees = 0;
uint private feePercent = 10;
uint private pyramidMultiplier = 300;
uint private payoutOrder = 0;
address private creator;
//Sets creator
function DynamicPyramid() {
creator = msg.sender;
}
modifier onlyowner {
if (msg.sender == creator) _;
}
struct Participant {
address etherAddress;
uint payout;
}
Participant[] private participants;
pragma solidity 0.5.0;
//Fallback function
function() {
init();
}
//init function run on fallback
function init() private {
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid
if (msg.value < 1 ether) {
collectedFees += msg.value;
return;
}
uint _fee = feePercent;
//50% fee rebate on any ether value of 50 or greater
if (msg.value >= 50 ether) _fee /= 2;
addPayout(_fee);
}
//Function called for valid tx to the contract
function addPayout(uint _fee) private {
//Adds new address to participant array
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100));
//These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan
if (participants.length == 10) pyramidMultiplier = 200;
else if (participants.length == 25) pyramidMultiplier = 150;
// collect fees and update contract balance
balance += (msg.value * (100 - _fee)) / 100;
collectedFees += (msg.value * _fee) / 100;
//Pays earlier participiants if balance sufficient
while (balance > participants[payoutOrder].payout) {
uint payoutToSend = participants[payoutOrder].payout;
participants[payoutOrder].etherAddress.send(payoutToSend);
balance -= participants[payoutOrder].payout;
payoutOrder += 1;
}
}
contract Rubixi {
//Declare variables for storage critical to contract
uint private balance = 0;
uint private collectedFees = 0;
uint private feePercent = 10;
uint private pyramidMultiplier = 300;
uint private payoutOrder = 0;
address payable private creator;
modifier onlyowner {
if (msg.sender == creator) _;
}
struct Participant {
address payable etherAddress;
uint payout;
}
//Fallback function
function() external payable {
init();
}
//Sets creator
function dynamicPyramid() public {
creator = msg.sender;
}
Participant[] private participants;
//Fee functions for creator
function collectAllFees() public onlyowner {
require(collectedFees == 0);
creator.transfer(collectedFees);
collectedFees = 0;
}
function collectFeesInEther(uint _amt) public onlyowner {
_amt *= 1 ether;
if (_amt > collectedFees) collectAllFees();
require(collectedFees == 0);
creator.transfer(_amt);
collectedFees -= _amt;
}
function collectPercentOfFees(uint _pcent) public onlyowner {
require(collectedFees == 0 || _pcent > 100);
uint feesToCollect = collectedFees / 100 * _pcent;
creator.transfer(feesToCollect);
collectedFees -= feesToCollect;
}
//Functions for changing variables related to the contract
function changeOwner(address payable _owner) public onlyowner {
creator = _owner;
}
function changeMultiplier(uint _mult) public onlyowner {
require(_mult > 300 || _mult < 120);
pyramidMultiplier = _mult;
}
function changeFeePercentage(uint _fee) public onlyowner {
require(_fee > 10);
feePercent = _fee;
}
//Functions to provide information to end-user using JSON interface or other interfaces
function currentMultiplier() public view returns (uint multiplier, string memory info) {
multiplier = pyramidMultiplier;
info = "This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.";
}
function currentFeePercentage() public view returns (uint fee, string memory info) {
fee = feePercent;
info = "Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)";
}
//Fee functions for creator
function collectAllFees() onlyowner {
if (collectedFees == 0) throw;
function currentPyramidBalanceApproximately() public view returns (uint pyramidBalance, string memory info) {
pyramidBalance = balance / 1 ether;
info = "All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to";
}
creator.send(collectedFees);
collectedFees = 0;
}
function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) {
balancePayout = participants[payoutOrder].payout / 1 ether;
}
function collectFeesInEther(uint _amt) onlyowner {
_amt *= 1 ether;
if (_amt > collectedFees) collectAllFees();
function feesSeperateFromBalanceApproximately() public view returns (uint fees) {
fees = collectedFees / 1 ether;
}
if (collectedFees == 0) throw;
creator.send(_amt);
collectedFees -= _amt;
}
function totalParticipants() public view returns (uint count) {
count = participants.length;
}
function collectPercentOfFees(uint _pcent) onlyowner {
if (collectedFees == 0 || _pcent > 100) throw;
function numberOfParticipantsWaitingForPayout() public view returns (uint count) {
count = participants.length - payoutOrder;
}
uint feesToCollect = collectedFees / 100 * _pcent;
creator.send(feesToCollect);
collectedFees -= feesToCollect;
function participantDetails(uint orderInPyramid) public view returns (address addr, uint payout) {
if (orderInPyramid <= participants.length) {
addr = participants[orderInPyramid].etherAddress;
payout = participants[orderInPyramid].payout / 1 ether;
}
}
//Functions for changing variables related to the contract
function changeOwner(address _owner) onlyowner {
creator = _owner;
//init function run on fallback
function init() private {
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid
if (msg.value < 1 ether) {
collectedFees += msg.value;
return;
}
function changeMultiplier(uint _mult) onlyowner {
if (_mult > 300 || _mult < 120) throw;
uint _fee = feePercent;
// 50% fee rebate on any ether value of 50 or greater
if (msg.value >= 50 ether) _fee /= 2;
pyramidMultiplier = _mult;
}
addPayout(_fee);
}
function changeFeePercentage(uint _fee) onlyowner {
if (_fee > 10) throw;
//Function called for valid tx to the contract
function addPayout(uint _fee) private {
//Adds new address to participant array
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100));
feePercent = _fee;
}
// These statements ensure a quicker payout system to
// later pyramid entrants, so the pyramid has a longer lifespan
if (participants.length == 10) pyramidMultiplier = 200;
else if (participants.length == 25) pyramidMultiplier = 150;
//Functions to provide information to end-user using JSON interface or other interfaces
function currentMultiplier() constant returns(uint multiplier, string info) {
multiplier = pyramidMultiplier;
info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.';
}
function currentFeePercentage() constant returns(uint fee, string info) {
fee = feePercent;
info = 'Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)';
}
// collect fees and update contract balance
balance += (msg.value * (100 - _fee)) / 100;
collectedFees += (msg.value * _fee) / 100;
function currentPyramidBalanceApproximately() constant returns(uint pyramidBalance, string info) {
pyramidBalance = balance / 1 ether;
info = 'All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to';
}
function nextPayoutWhenPyramidBalanceTotalsApproximately() constant returns(uint balancePayout) {
balancePayout = participants[payoutOrder].payout / 1 ether;
}
function feesSeperateFromBalanceApproximately() constant returns(uint fees) {
fees = collectedFees / 1 ether;
}
function totalParticipants() constant returns(uint count) {
count = participants.length;
}
function numberOfParticipantsWaitingForPayout() constant returns(uint count) {
count = participants.length - payoutOrder;
}
//Pays earlier participiants if balance sufficient
while (balance > participants[payoutOrder].payout) {
uint payoutToSend = participants[payoutOrder].payout;
participants[payoutOrder].etherAddress.transfer(payoutToSend);
function participantDetails(uint orderInPyramid) constant returns(address Address, uint Payout) {
if (orderInPyramid <= participants.length) {
Address = participants[orderInPyramid].etherAddress;
Payout = participants[orderInPyramid].payout / 1 ether;
}
balance -= participants[payoutOrder].payout;
payoutOrder += 1;
}
}
}

@ -1,6 +1,9 @@
pragma solidity 0.5.0;
contract Suicide {
function kill(address addr) {
function kill(address payable addr) public {
selfdestruct(addr);
}

@ -1,9 +1,12 @@
pragma solidity 0.5.0;
contract Under {
mapping(address => uint) balances;
uint public totalSupply;
function Token(uint _initialSupply) {
constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
@ -14,7 +17,7 @@ contract Under {
return true;
}
function balanceOf(address _owner) public constant returns (uint balance) {
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}

@ -1,20 +1,21 @@
pragma solidity ^0.4.16;
pragma solidity 0.5.0;
contract WeakRandom {
struct Contestant {
address addr;
address payable addr;
uint gameId;
}
uint public constant prize = 2.5 ether;
uint public constant totalTickets = 50;
uint public constant pricePerTicket = prize / totalTickets;
uint public prize = 2.5 ether;
uint public totalTickets = 50;
uint public pricePerTicket = prize / totalTickets;
uint public gameId = 1;
uint public nextTicket = 0;
mapping (uint => Contestant) public contestants;
function () payable public {
function () payable external {
uint moneySent = msg.value;
while (moneySent >= pricePerTicket && nextTicket < totalTickets) {
@ -37,10 +38,10 @@ contract WeakRandom {
address seed1 = contestants[uint(block.coinbase) % totalTickets].addr;
address seed2 = contestants[uint(msg.sender) % totalTickets].addr;
uint seed3 = block.difficulty;
bytes32 randHash = keccak256(seed1, seed2, seed3);
bytes32 randHash = keccak256(abi.encode(seed1, seed2, seed3));
uint winningNumber = uint(randHash) % totalTickets;
address winningAddress = contestants[winningNumber].addr;
address payable winningAddress = contestants[winningNumber].addr;
gameId++;
nextTicket = 0;

@ -1,126 +1 @@
{
"error": null,
"issues": [
{
"address": 661,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.",
"function": "thisisfine()",
"swc-id": "107",
"min_gas_used": 643,
"max_gas_used": 1254,
"title": "Message call to external contract",
"type": "Informational"
},
{
"address": 666,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "thisisfine()",
"swc-id": "104",
"min_gas_used": 1352,
"max_gas_used": 35963,
"title": "Unchecked CALL return value",
"type": "Informational"
},
{
"address": 779,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `setstoredaddress(address)`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.",
"function": "callstoredaddress()",
"swc-id": "107",
"min_gas_used": 687,
"max_gas_used": 1298,
"title": "Message call to external contract",
"type": "Warning"
},
{
"address": 779,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location.",
"function": "callstoredaddress()",
"swc-id": "114",
"min_gas_used": 687,
"max_gas_used": 1298,
"title": "Transaction order dependence",
"type": "Warning"
},
{
"address": 784,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "callstoredaddress()",
"swc-id": "104",
"min_gas_used": 1396,
"max_gas_used": 36007,
"title": "Unchecked CALL return value",
"type": "Informational"
},
{
"address": 858,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.",
"function": "_function_0xe11f493e",
"swc-id": "107",
"min_gas_used": 709,
"max_gas_used": 1320,
"title": "Message call to external contract",
"type": "Informational"
},
{
"address": 869,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.",
"function": "_function_0xe11f493e",
"swc-id": "107",
"min_gas_used": 709,
"max_gas_used": 1320,
"title": "State change after external call",
"type": "Warning"
},
{
"address": 871,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0xe11f493e",
"swc-id": "104",
"min_gas_used": 6432,
"max_gas_used": 61043,
"title": "Unchecked CALL return value",
"type": "Informational"
},
{
"address": 912,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.",
"function": "calluseraddress(address)",
"swc-id": "107",
"min_gas_used": 335,
"max_gas_used": 616,
"title": "Message call to external contract",
"type": "Warning"
},
{
"address": 918,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "calluseraddress(address)",
"swc-id": "104",
"min_gas_used": 1046,
"max_gas_used": 35327,
"title": "Unchecked CALL return value",
"type": "Informational"
}
],
"success": true
}
{"error": null, "issues": [{"address": 661, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "thisisfine()", "max_gas_used": 1254, "min_gas_used": 643, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 666, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "thisisfine()", "max_gas_used": 35963, "min_gas_used": 1352, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "callstoredaddress()", "max_gas_used": 1298, "min_gas_used": 687, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 784, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "callstoredaddress()", "max_gas_used": 36007, "min_gas_used": 1396, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 858, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "reentrancy()", "max_gas_used": 1320, "min_gas_used": 709, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 871, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "reentrancy()", "max_gas_used": 61043, "min_gas_used": 6432, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 912, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "calluseraddress(address)", "max_gas_used": 616, "min_gas_used": 335, "swc-id": "107", "title": "External call to user-supplied address", "type": "Warning"}, {"address": 918, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "calluseraddress(address)", "max_gas_used": 35327, "min_gas_used": 1046, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true}

@ -1,6 +1,6 @@
# Analysis results for test-filename.sol
## Message call to external contract
## External call
- SWC ID: 107
- Type: Informational
- Contract: Unknown
@ -10,7 +10,7 @@
### Description
This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
## Unchecked CALL return value
- SWC ID: 104
@ -24,21 +24,9 @@ This contract executes a message call to to another contract. Make sure that the
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Message call to external contract
## External call
- SWC ID: 107
- Type: Warning
- Contract: Unknown
- Function name: `callstoredaddress()`
- PC address: 779
- Estimated Gas Usage: 687 - 1298
### Description
This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `setstoredaddress(address)`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.
## Transaction order dependence
- SWC ID: 114
- Type: Warning
- Type: Informational
- Contract: Unknown
- Function name: `callstoredaddress()`
- PC address: 779
@ -46,7 +34,7 @@ This contract executes a message call to an address found at storage slot 1. Thi
### Description
Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
## Unchecked CALL return value
- SWC ID: 104
@ -60,35 +48,23 @@ Possible transaction order dependence vulnerability: The value or direction of t
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Message call to external contract
## External call
- SWC ID: 107
- Type: Informational
- Contract: Unknown
- Function name: `_function_0xe11f493e`
- Function name: `reentrancy()`
- PC address: 858
- Estimated Gas Usage: 709 - 1320
### Description
This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.
## State change after external call
- SWC ID: 107
- Type: Warning
- Contract: Unknown
- Function name: `_function_0xe11f493e`
- PC address: 869
- Estimated Gas Usage: 709 - 1320
### Description
The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
## Unchecked CALL return value
- SWC ID: 104
- Type: Informational
- Contract: Unknown
- Function name: `_function_0xe11f493e`
- Function name: `reentrancy()`
- PC address: 871
- Estimated Gas Usage: 6432 - 61043
@ -96,7 +72,7 @@ The contract account state is changed after an external call. Consider that the
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Message call to external contract
## External call to user-supplied address
- SWC ID: 107
- Type: Warning
- Contract: Unknown
@ -106,7 +82,7 @@ The return value of an external call is not checked. Note that execution continu
### Description
This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.
The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.
## Unchecked CALL return value
- SWC ID: 104

@ -1,11 +1,11 @@
==== Message call to external contract ====
==== External call ====
SWC ID: 107
Type: Informational
Contract: Unknown
Function name: thisisfine()
PC address: 661
Estimated Gas Usage: 643 - 1254
This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
--------------------
==== Unchecked CALL return value ====
@ -18,24 +18,14 @@ Estimated Gas Usage: 1352 - 35963
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------
==== Message call to external contract ====
==== External call ====
SWC ID: 107
Type: Warning
Contract: Unknown
Function name: callstoredaddress()
PC address: 779
Estimated Gas Usage: 687 - 1298
This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `setstoredaddress(address)`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.
--------------------
==== Transaction order dependence ====
SWC ID: 114
Type: Warning
Type: Informational
Contract: Unknown
Function name: callstoredaddress()
PC address: 779
Estimated Gas Usage: 687 - 1298
Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
--------------------
==== Unchecked CALL return value ====
@ -48,44 +38,34 @@ Estimated Gas Usage: 1396 - 36007
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------
==== Message call to external contract ====
==== External call ====
SWC ID: 107
Type: Informational
Contract: Unknown
Function name: _function_0xe11f493e
Function name: reentrancy()
PC address: 858
Estimated Gas Usage: 709 - 1320
This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.
--------------------
==== State change after external call ====
SWC ID: 107
Type: Warning
Contract: Unknown
Function name: _function_0xe11f493e
PC address: 869
Estimated Gas Usage: 709 - 1320
The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.
The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.
--------------------
==== Unchecked CALL return value ====
SWC ID: 104
Type: Informational
Contract: Unknown
Function name: _function_0xe11f493e
Function name: reentrancy()
PC address: 871
Estimated Gas Usage: 6432 - 61043
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
--------------------
==== Message call to external contract ====
==== External call to user-supplied address ====
SWC ID: 107
Type: Warning
Contract: Unknown
Function name: calluseraddress(address)
PC address: 912
Estimated Gas Usage: 335 - 616
This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.
The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.
--------------------
==== Unchecked CALL return value ====

@ -1,36 +1,36 @@
{
"error": null,
"issues": [
{
"address": 158,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The arithmetic operation can result in integer overflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Overflow",
"type": "Warning"
},
{
"address": 278,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The arithmetic operation can result in integer overflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Overflow",
"type": "Warning"
},
{
"address": 378,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The substraction can result in an integer underflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Underflow",
"type": "Warning"
}
],
"success": true
"error": null,
"issues": [
{
"address": 158,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The arithmetic operation can result in integer overflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Overflow",
"type": "Warning",
},
{
"address": 278,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The arithmetic operation can result in integer overflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Overflow",
"type": "Warning",
},
{
"address": 378,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The substraction can result in an integer underflow.\n",
"function": "_function_0x83f12fec",
"swc-id": "101",
"title": "Integer Underflow",
"type": "Warning",
},
],
"success": true,
}

@ -1,30 +1,5 @@
{
"error": null,
"issues": [
{
"address": 722,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "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.",
"function": "withdrawfunds()",
"max_gas_used": 1749,
"min_gas_used": 1138,
"swc-id": "105",
"title": "Ether thief",
"type": "Warning"
},
{
"address": 883,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This binary add operation can result in integer overflow.\n",
"function": "invest()",
"max_gas_used": 1856,
"min_gas_used": 1571,
"swc-id": "101",
"title": "Integer Overflow",
"type": "Warning"
}
],
"issues": [],
"success": true
}

@ -1,25 +1,3 @@
# Analysis results for test-filename.sol
# Analysis results for None
## Ether thief
- SWC ID: 105
- Type: Warning
- Contract: Unknown
- Function name: `withdrawfunds()`
- PC address: 722
- Estimated Gas Usage: 1138 - 1749
### Description
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.
## Integer Overflow
- SWC ID: 101
- Type: Warning
- Contract: Unknown
- Function name: `invest()`
- PC address: 883
- Estimated Gas Usage: 1571 - 1856
### Description
This binary add operation can result in integer overflow.
The analysis was completed successfully. No issues were detected.

@ -1,21 +1 @@
==== Ether thief ====
SWC ID: 105
Type: Warning
Contract: Unknown
Function name: withdrawfunds()
PC address: 722
Estimated Gas Usage: 1138 - 1749
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.
--------------------
==== Integer Overflow ====
SWC ID: 101
Type: Warning
Contract: Unknown
Function name: invest()
PC address: 883
Estimated Gas Usage: 1571 - 1856
This binary add operation can result in integer overflow.
--------------------
The analysis was completed successfully. No issues were detected.

@ -7,9 +7,9 @@
"debug": "<DEBUG-DATA>",
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.",
"function": "assert3(uint256)",
"swc-id": "110",
"min_gas_used": 206,
"max_gas_used": 301,
"min_gas_used": 206,
"swc-id": "110",
"title": "Exception state",
"type": "Informational"
},
@ -19,9 +19,9 @@
"debug": "<DEBUG-DATA>",
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.",
"function": "arrayaccess(uint256)",
"swc-id": "110",
"min_gas_used": 256,
"max_gas_used": 351,
"min_gas_used": 256,
"swc-id": "110",
"title": "Exception state",
"type": "Informational"
},
@ -31,9 +31,9 @@
"debug": "<DEBUG-DATA>",
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.",
"function": "divisionby0(uint256)",
"swc-id": "110",
"min_gas_used": 272,
"max_gas_used": 367,
"min_gas_used": 272,
"swc-id": "110",
"title": "Exception state",
"type": "Informational"
},
@ -43,9 +43,9 @@
"debug": "<DEBUG-DATA>",
"description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.",
"function": "assert1()",
"swc-id": "110",
"min_gas_used": 268,
"max_gas_used": 363,
"min_gas_used": 268,
"swc-id": "110",
"title": "Exception state",
"type": "Informational"
}

@ -1,54 +1 @@
{
"error": null,
"issues": [
{
"address": 626,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0x141f32ff",
"swc-id": "104",
"min_gas_used": 1104,
"max_gas_used": 35856,
"title": "Unchecked CALL return value",
"type": "Informational"
},
{
"address": 857,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0x9b58bc26",
"swc-id": "104",
"min_gas_used": 1167,
"max_gas_used": 35919,
"title": "Unchecked CALL return value",
"type": "Informational"
},
{
"address": 1038,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.",
"function": "_function_0xeea4c864",
"swc-id": "107",
"min_gas_used": 477,
"max_gas_used": 1229,
"title": "Message call to external contract",
"type": "Warning"
},
{
"address": 1046,
"contract": "Unknown",
"debug": "<DEBUG-DATA>",
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.",
"function": "_function_0xeea4c864",
"swc-id": "104",
"min_gas_used": 1192,
"max_gas_used": 35944,
"title": "Unchecked CALL return value",
"type": "Informational"
}
],
"success": true
}
{"error": null, "issues": [{"address": 626, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "max_gas_used": 35856, "min_gas_used": 1104, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "max_gas_used": 35919, "min_gas_used": 1167, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "_function_0xeea4c864", "max_gas_used": 1229, "min_gas_used": 477, "swc-id": "107", "title": "External call to user-supplied address", "type": "Warning"}, {"address": 1046, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "max_gas_used": 35944, "min_gas_used": 1192, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true}

@ -24,7 +24,7 @@ The return value of an external call is not checked. Note that execution continu
The return value of an external call is not checked. Note that execution continue even if the called contract throws.
## Message call to external contract
## External call to user-supplied address
- SWC ID: 107
- Type: Warning
- Contract: Unknown
@ -34,7 +34,7 @@ The return value of an external call is not checked. Note that execution continu
### Description
This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.
The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.
## Unchecked CALL return value
- SWC ID: 104

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save