mirror of https://github.com/ConsenSys/mythril
parent
3bbea89b80
commit
78a720ed31
@ -0,0 +1,6 @@ |
||||
What is Mythril Classic? |
||||
======================== |
||||
|
||||
Mythril Classic is a security analysis tool for Ethereum smart contracts. It was `introduced at HITBSecConf 2018 <https://github.com/b-mueller/smashing-smart-contracts/blob/master/smashing-smart-contracts-1of1.pdf>`_. |
||||
|
||||
Mythril Classic detects a range of security issues, including integer underflows, owner-overwrite-to-Ether-withdrawal, and others. Note that Mythril is targeted at finding common vulnerabilities, and is not able to discover issues in the business logic of an application. Furthermore, Mythril and symbolic executors are generally unsound, as they are often unable to explore all possible states of a program. |
@ -0,0 +1,11 @@ |
||||
Analysis Modules |
||||
================ |
||||
|
||||
Mythril Classic's detection capabilities are written in modules in the `/analysis/modules <https://github.com/ConsenSys/mythril-classic/tree/master/mythril/analysis/modules>`_ directory. |
||||
|
||||
|
||||
.. toctree:: |
||||
:maxdepth: 2 |
||||
|
||||
module-list.rst |
||||
create-module.rst |
@ -0,0 +1,4 @@ |
||||
Creating a Module |
||||
================= |
||||
|
||||
Create a module in the :code:`analysis/modules` directory, and create an instance of a class that inherits :code:`DetectionModule` named :code:`detector`. Take a look at the `suicide module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/suicide.py>`_ as an example. |
@ -0,0 +1,66 @@ |
||||
Installation and Setup |
||||
====================== |
||||
|
||||
Mythril can be setup using different methods. |
||||
|
||||
************** |
||||
PyPI on Mac OS |
||||
************** |
||||
|
||||
.. code-block:: bash |
||||
|
||||
brew update |
||||
brew upgrade |
||||
brew tap ethereum/ethereum |
||||
brew install leveldb |
||||
brew install solidity |
||||
pip3 install mythril |
||||
|
||||
|
||||
************** |
||||
PyPI on Ubuntu |
||||
************** |
||||
|
||||
.. code-block:: bash |
||||
|
||||
# Update |
||||
sudo apt update |
||||
|
||||
# Install solc |
||||
sudo apt install software-properties-common |
||||
sudo add-apt-repository ppa:ethereum/ethereum |
||||
sudo apt install solc |
||||
|
||||
# Install libssl-dev, python3-dev, and python3-pip |
||||
sudo apt install libssl-dev python3-dev python3-pip |
||||
|
||||
# Install mythril |
||||
pip3 install mythril |
||||
myth --version |
||||
|
||||
|
||||
****** |
||||
Docker |
||||
****** |
||||
|
||||
All Mythril releases, starting from v0.18.3, are published to DockerHub as Docker images under the :code:`mythril/myth` name. |
||||
|
||||
After installing `Docker CE <https://docs.docker.com/install/>`_: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
# Pull the latest release of mythril/myth |
||||
$ docker pull mythril/myth |
||||
|
||||
Use :code:`docker run mythril/myth` the same way you would use the :code:`myth` command |
||||
|
||||
.. code-block:: bash |
||||
|
||||
docker run mythril/myth --help |
||||
docker run mythril/myth -dc "0x6060" |
||||
|
||||
To pass a file from your host machine to the dockerized Mythril, you must mount its containing folder to the container properly. For :code:`contract.sol` in the current working directory, do: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
docker run -v $(pwd):/tmp mythril/myth -x /tmp/contract.sol |
@ -0,0 +1,68 @@ |
||||
Modules |
||||
======= |
||||
|
||||
*********************************** |
||||
Delegate Call To Untrusted Contract |
||||
*********************************** |
||||
|
||||
The `delegatecall module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/delegatecall.py>`_ detects `SWC-112 (DELEGATECALL to Untrusted Callee) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-112>`_. |
||||
|
||||
*********************************** |
||||
Dependence on Predictable Variables |
||||
*********************************** |
||||
|
||||
The `predictable variables module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/dependence_on_predictable_vars.py>`_ detects `SWC-120 (Weak Randomness) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-120>`_ and `SWC-116 (Timestamp Dependence) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-116>`_. |
||||
|
||||
****************** |
||||
Deprecated Opcodes |
||||
****************** |
||||
|
||||
The `deprecated opcodes module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/deprecated_ops.py>`_ detects `SWC-111 (Use of Deprecated Functions) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-111>`_. |
||||
|
||||
*********** |
||||
Ether Thief |
||||
*********** |
||||
|
||||
The `Ether Thief module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/ether_thief.py>`_ detects `SWC-105 (Unprotected Ether Withdrawal) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-105>`_. |
||||
|
||||
********** |
||||
Exceptions |
||||
********** |
||||
|
||||
The `exceptions module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/exceptions.py>`_ detects `SWC-110 (Assert Violation) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-110>`_. |
||||
|
||||
************** |
||||
External Calls |
||||
************** |
||||
|
||||
The `external calls module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/external_calls.py>`_ detects `SWC-117 (Reentrancy) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-117>`_ by detecting state changes after calls to external contracts. |
||||
|
||||
******* |
||||
Integer |
||||
******* |
||||
|
||||
The `integer module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/integer.py>`_ detects `SWC-101 (Integer Overflow and Underflow) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-101>`_. |
||||
|
||||
************** |
||||
Multiple Sends |
||||
************** |
||||
|
||||
The `multiple sends module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/multiple_sends.py>`_ detects `SWC-113 (Denial of Service with Failed Call) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-113>`_ by checking for multiple calls or sends in a single transaction. |
||||
|
||||
******* |
||||
Suicide |
||||
******* |
||||
|
||||
The `suicide module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/suicide.py>`_ detects `SWC-106 (Unprotected SELFDESTRUCT) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-106>`_. |
||||
|
||||
**************************** |
||||
Transaction Order Dependence |
||||
**************************** |
||||
|
||||
The `transaction order dependence module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/transaction_order_dependence.py>`_ detects `SWC-114 (Transaction Order Dependence / Race Conditions) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-114>`_. |
||||
|
||||
**************** |
||||
Unchecked Retval |
||||
**************** |
||||
|
||||
The `unchecked retval module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/unchecked_retval.py>`_ detects `SWC-104 (Unchecked Call Return Value) <https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-104>`_. |
@ -1,7 +0,0 @@ |
||||
mythril |
||||
======= |
||||
|
||||
.. toctree:: |
||||
:maxdepth: 4 |
||||
|
||||
mythril |
@ -0,0 +1,90 @@ |
||||
Security Analysis |
||||
================= |
||||
|
||||
Run :code:`myth -x` with one of the input options described below will run the analysis modules in the `/analysis/modules <https://github.com/ConsenSys/mythril-classic/tree/master/mythril/analysis/modules>`_ directory. |
||||
|
||||
*********************** |
||||
Analyzing Solidity Code |
||||
*********************** |
||||
|
||||
In order to work with Solidity source code files, the `solc command line compiler <https://solidity.readthedocs.io/en/develop/using-the-compiler.html>`_ needs to be installed and in PATH. You can then provide the source file(s) as positional arguments. |
||||
|
||||
.. code-block:: bash |
||||
|
||||
$ myth -x ether_send.sol |
||||
==== Unprotected Ether Withdrawal ==== |
||||
SWC ID: 105 |
||||
Severity: High |
||||
Contract: Crowdfunding |
||||
Function name: withdrawfunds() |
||||
PC address: 730 |
||||
Estimated Gas Usage: 1132 - 1743 |
||||
Anyone can withdraw ETH from the contract account. |
||||
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. |
||||
-------------------- |
||||
In file: tests/testdata/input_contracts/ether_send.sol:21 |
||||
|
||||
msg.sender.transfer(address(this).balance) |
||||
|
||||
-------------------- |
||||
|
||||
If an input file contains multiple contract definitions, Mythril analyzes the *last* bytecode output produced by solc. You can override this by specifying the contract name explicitly: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
myth -x OmiseGo.sol:OMGToken |
||||
|
||||
Specifying Solc Versions |
||||
######################## |
||||
|
||||
You can specify a version of the solidity compiler to be used with :code:`--solv <version number>`. Please be aware that this uses `py-solc <https://github.com/ethereum/py-solc>`_ and will only work on Linux and macOS. It will check the version of solc in your path, and if this is not what is specified, it will download binaries on Linux or try to compile from source on macOS. |
||||
|
||||
|
||||
Output Formats |
||||
############## |
||||
|
||||
By default, analysis results are printed to the terminal in text format. You can change the output format with the :code:`-o` argument: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
myth -xo jsonv2 underflow.sol |
||||
|
||||
Available formats are :code:`text`, :code:`markdown`, :code:`json`, and :code:`jsonv2`. For integration with other tools, :code:`jsonv2` is generally preferred over :code:`json` because it is consistent with other `MythX <https://mythx.io>`_ tools. |
||||
|
||||
**************************** |
||||
Analyzing On-Chain Contracts |
||||
**************************** |
||||
|
||||
When analyzing contracts on the blockchain, Mythril will by default attempt to query INFURA. You can use the built-in INFURA support or manually configure the RPC settings with the :code:`--rpc` argument. |
||||
|
||||
+--------------------------------+-------------------------------------------------+ |
||||
| :code:`--rpc ganache` | Connect to local Ganache | |
||||
+--------------------------------+-------------------------------------------------+ |
||||
| :code:`--rpc infura-[netname]` | Connect to mainnet, rinkeby, kovan, or ropsten. | |
||||
+--------------------------------+-------------------------------------------------+ |
||||
| :code:`--rpc host:port` | Connect to custom rpc | |
||||
+--------------------------------+-------------------------------------------------+ |
||||
| :code:`--rpctls <True/False>` | RPC connection over TLS (default: False) | |
||||
+--------------------------------+-------------------------------------------------+ |
||||
|
||||
To specify a contract address, use :code:`-a <address>` |
||||
|
||||
Analyze mainnet contract via INFURA: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
myth -x -a 0x5c436ff914c458983414019195e0f4ecbef9e6dd |
||||
|
||||
Adding the :code:`-l` flag will cause mythril to automatically retrieve dependencies, such as dynamically linked library contracts: |
||||
|
||||
.. code-block:: bash |
||||
|
||||
myth -xla 0xEbFD99838cb0c132016B9E117563CB41f2B02264 -v4 |
||||
|
||||
****************** |
||||
Speed vs. Coverage |
||||
****************** |
||||
|
||||
The execution timeout can be specified with the :code:`--execution-timeout <seconds>` argument. When the timeout is reached, mythril will stop analysis and print out all currently found issues. |
||||
|
||||
The maximum recursion depth for the symbolic execution engine can be controlled with the :code:`--max-depth` argument. The default value is 22. Lowering this value will decrease the number of explored states and analysis time, while increasing this number will increase the number of explored states and increase analysis time. For some contracts, it helps to fine tune this number to get the best analysis results. |
@ -0,0 +1,84 @@ |
||||
from mythril.laser.ethereum.svm import LaserEVM |
||||
from time import time |
||||
import matplotlib.pyplot as plt |
||||
import logging |
||||
|
||||
log = logging.getLogger(__name__) |
||||
|
||||
|
||||
class BenchmarkPlugin: |
||||
"""Benchmark Plugin |
||||
|
||||
This plugin aggregates the following information: |
||||
- duration |
||||
- code coverage over time |
||||
- final code coverage |
||||
- total number of executed instructions |
||||
|
||||
""" |
||||
|
||||
def __init__(self, name=None): |
||||
"""Creates BenchmarkPlugin |
||||
|
||||
:param name: name of this benchmark, used for storing the results |
||||
""" |
||||
self.nr_of_executed_insns = 0 |
||||
self.begin = None |
||||
self.end = None |
||||
self.coverage = {} |
||||
self.name = name |
||||
|
||||
def initialize(self, symbolic_vm: LaserEVM): |
||||
"""Initializes the BenchmarkPlugin |
||||
|
||||
Introduces hooks in symbolic_vm to track the desired values |
||||
:param symbolic_vm: Symbolic virtual machine to analyze |
||||
""" |
||||
self._reset() |
||||
|
||||
@symbolic_vm.laser_hook("execute_state") |
||||
def execute_state_hook(_): |
||||
current_time = time() - self.begin |
||||
self.nr_of_executed_insns += 1 |
||||
|
||||
for key, value in symbolic_vm.coverage.items(): |
||||
try: |
||||
self.coverage[key][current_time] = sum(value[1]) * 100 / value[0] |
||||
except KeyError: |
||||
self.coverage[key] = {} |
||||
self.coverage[key][current_time] = sum(value[1]) * 100 / value[0] |
||||
|
||||
@symbolic_vm.laser_hook("start_sym_exec") |
||||
def start_sym_exec_hook(): |
||||
self.begin = time() |
||||
|
||||
@symbolic_vm.laser_hook("stop_sym_exec") |
||||
def stop_sym_exec_hook(): |
||||
self.end = time() |
||||
|
||||
self._write_to_graph() |
||||
self._store_report() |
||||
|
||||
def _reset(self): |
||||
"""Reset this plugin""" |
||||
self.nr_of_executed_insns = 0 |
||||
self.begin = None |
||||
self.end = None |
||||
self.coverage = {} |
||||
|
||||
def _store_report(self): |
||||
"""Store the results of this plugin""" |
||||
pass |
||||
|
||||
def _write_to_graph(self): |
||||
"""Write the coverage results to a graph""" |
||||
traces = [] |
||||
for byte_code, trace_data in self.coverage.items(): |
||||
traces += [list(trace_data.keys()), list(trace_data.values()), "r--"] |
||||
|
||||
plt.plot(*traces) |
||||
plt.axis([0, self.end - self.begin, 0, 100]) |
||||
plt.xlabel("Duration (seconds)") |
||||
plt.ylabel("Coverage (percentage)") |
||||
|
||||
plt.savefig("{}.png".format(self.name)) |
@ -0,0 +1,225 @@ |
||||
from typing import Optional, Union, cast, Callable |
||||
|
||||
import z3 |
||||
|
||||
from mythril.laser.smt.bitvec import BitVec, Bool, And, Annotations |
||||
from mythril.laser.smt.bool import Or |
||||
|
||||
import operator |
||||
|
||||
|
||||
def _arithmetic_helper( |
||||
a: "BitVecFunc", b: Union[BitVec, int], operation: Callable |
||||
) -> "BitVecFunc": |
||||
""" |
||||
Helper function for arithmetic operations on BitVecFuncs. |
||||
|
||||
:param a: The BitVecFunc to perform the operation on. |
||||
:param b: A BitVec or int to perform the operation on. |
||||
:param operation: The arithmetic operation to perform. |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
if isinstance(b, int): |
||||
b = BitVec(z3.BitVecVal(b, a.size())) |
||||
|
||||
raw = operation(a.raw, b.raw) |
||||
union = a.annotations + b.annotations |
||||
|
||||
if isinstance(b, BitVecFunc): |
||||
# TODO: Find better value to set input and name to in this case? |
||||
return BitVecFunc(raw=raw, func_name=None, input_=None, annotations=union) |
||||
|
||||
return BitVecFunc( |
||||
raw=raw, func_name=a.func_name, input_=a.input_, annotations=union |
||||
) |
||||
|
||||
|
||||
def _comparison_helper( |
||||
a: "BitVecFunc", |
||||
b: Union[BitVec, int], |
||||
operation: Callable, |
||||
default_value: bool, |
||||
inputs_equal: bool, |
||||
) -> Bool: |
||||
""" |
||||
Helper function for comparison operations with BitVecFuncs. |
||||
|
||||
:param a: The BitVecFunc to compare. |
||||
:param b: A BitVec or int to compare to. |
||||
:param operation: The comparison operation to perform. |
||||
:return: The resulting Bool |
||||
""" |
||||
# Is there some hack for gt/lt comparisons? |
||||
if isinstance(b, int): |
||||
b = BitVec(z3.BitVecVal(b, a.size())) |
||||
|
||||
union = a.annotations + b.annotations |
||||
|
||||
if not a.symbolic and not b.symbolic: |
||||
return Bool(z3.BoolVal(operation(a.value, b.value)), annotations=union) |
||||
|
||||
if ( |
||||
not isinstance(b, BitVecFunc) |
||||
or not a.func_name |
||||
or not a.input_ |
||||
or not a.func_name == b.func_name |
||||
): |
||||
return Bool(z3.BoolVal(default_value), annotations=union) |
||||
|
||||
return And( |
||||
Bool(cast(z3.BoolRef, operation(a.raw, b.raw)), annotations=union), |
||||
a.input_ == b.input_ if inputs_equal else a.input_ != b.input_, |
||||
) |
||||
|
||||
|
||||
class BitVecFunc(BitVec): |
||||
"""A bit vector function symbol. Used in place of functions like sha3.""" |
||||
|
||||
def __init__( |
||||
self, |
||||
raw: z3.BitVecRef, |
||||
func_name: Optional[str], |
||||
input_: Union[int, "BitVec"] = None, |
||||
annotations: Optional[Annotations] = None, |
||||
): |
||||
""" |
||||
|
||||
:param raw: The raw bit vector symbol |
||||
:param func_name: The function name. e.g. sha3 |
||||
:param input: The input to the functions |
||||
:param annotations: The annotations the BitVecFunc should start with |
||||
""" |
||||
|
||||
self.func_name = func_name |
||||
self.input_ = input_ |
||||
super().__init__(raw, annotations) |
||||
|
||||
def __add__(self, other: Union[int, "BitVec"]) -> "BitVecFunc": |
||||
"""Create an addition expression. |
||||
|
||||
:param other: The int or BitVec to add to this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.add) |
||||
|
||||
def __sub__(self, other: Union[int, "BitVec"]) -> "BitVecFunc": |
||||
"""Create a subtraction expression. |
||||
|
||||
:param other: The int or BitVec to subtract from this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.sub) |
||||
|
||||
def __mul__(self, other: "BitVec") -> "BitVecFunc": |
||||
"""Create a multiplication expression. |
||||
|
||||
:param other: The int or BitVec to multiply to this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.mul) |
||||
|
||||
def __truediv__(self, other: "BitVec") -> "BitVecFunc": |
||||
"""Create a signed division expression. |
||||
|
||||
:param other: The int or BitVec to divide this BitVecFunc by |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.truediv) |
||||
|
||||
def __and__(self, other: Union[int, "BitVec"]) -> "BitVecFunc": |
||||
"""Create an and expression. |
||||
|
||||
:param other: The int or BitVec to and with this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.and_) |
||||
|
||||
def __or__(self, other: "BitVec") -> "BitVecFunc": |
||||
"""Create an or expression. |
||||
|
||||
:param other: The int or BitVec to or with this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.or_) |
||||
|
||||
def __xor__(self, other: "BitVec") -> "BitVecFunc": |
||||
"""Create a xor expression. |
||||
|
||||
:param other: The int or BitVec to xor with this BitVecFunc |
||||
:return: The resulting BitVecFunc |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.xor) |
||||
|
||||
def __lt__(self, other: "BitVec") -> Bool: |
||||
"""Create a signed less than expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return _comparison_helper( |
||||
self, other, operator.lt, default_value=False, inputs_equal=False |
||||
) |
||||
|
||||
def __gt__(self, other: "BitVec") -> Bool: |
||||
"""Create a signed greater than expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return _comparison_helper( |
||||
self, other, operator.gt, default_value=False, inputs_equal=False |
||||
) |
||||
|
||||
def __le__(self, other: "BitVec") -> Bool: |
||||
"""Create a signed less than or equal to expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return Or(self < other, self == other) |
||||
|
||||
def __ge__(self, other: "BitVec") -> Bool: |
||||
"""Create a signed greater than or equal to expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return Or(self > other, self == other) |
||||
|
||||
# MYPY: fix complains about overriding __eq__ |
||||
def __eq__(self, other: Union[int, "BitVec"]) -> Bool: # type: ignore |
||||
"""Create an equality expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return _comparison_helper( |
||||
self, other, operator.eq, default_value=False, inputs_equal=True |
||||
) |
||||
|
||||
# MYPY: fix complains about overriding __ne__ |
||||
def __ne__(self, other: Union[int, "BitVec"]) -> Bool: # type: ignore |
||||
"""Create an inequality expression. |
||||
|
||||
:param other: The int or BitVec to compare to this BitVecFunc |
||||
:return: The resulting Bool |
||||
""" |
||||
return _comparison_helper( |
||||
self, other, operator.eq, default_value=True, inputs_equal=False |
||||
) |
||||
|
||||
def __lshift__(self, other: Union[int, "BitVec"]) -> "BitVec": |
||||
""" |
||||
Left shift operation |
||||
:param other: The int or BitVec to shift on |
||||
:return The resulting left shifted output |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.lshift) |
||||
|
||||
def __rshift__(self, other: Union[int, "BitVec"]) -> "BitVec": |
||||
""" |
||||
Right shift operation |
||||
:param other: The int or BitVec to shift on |
||||
:return The resulting right shifted output: |
||||
""" |
||||
return _arithmetic_helper(self, other, operator.rshift) |
@ -0,0 +1,3 @@ |
||||
from mythril.laser.smt.solver.solver import Solver, Optimize, BaseSolver |
||||
from mythril.laser.smt.solver.independence_solver import IndependenceSolver |
||||
from mythril.laser.smt.solver.solver_statistics import SolverStatistics |
@ -0,0 +1,43 @@ |
||||
from time import time |
||||
|
||||
from mythril.support.support_utils import Singleton |
||||
|
||||
from typing import Callable |
||||
|
||||
|
||||
def stat_smt_query(func: Callable): |
||||
"""Measures statistics for annotated smt query check function""" |
||||
stat_store = SolverStatistics() |
||||
|
||||
def function_wrapper(*args, **kwargs): |
||||
if not stat_store.enabled: |
||||
return func(*args, **kwargs) |
||||
|
||||
stat_store.query_count += 1 |
||||
begin = time() |
||||
|
||||
result = func(*args, **kwargs) |
||||
|
||||
end = time() |
||||
stat_store.solver_time += end - begin |
||||
|
||||
return result |
||||
|
||||
return function_wrapper |
||||
|
||||
|
||||
class SolverStatistics(object, metaclass=Singleton): |
||||
""" Solver Statistics Class |
||||
|
||||
Keeps track of the important statistics around smt queries |
||||
""" |
||||
|
||||
def __init__(self): |
||||
self.enabled = False |
||||
self.query_count = 0 |
||||
self.solver_time = 0 |
||||
|
||||
def __repr__(self): |
||||
return "Query count: {} \nSolver time: {}".format( |
||||
self.query_count, self.solver_time |
||||
) |
@ -0,0 +1,721 @@ |
||||
#!/usr/bin/env python3 |
||||
# -*- coding: utf-8 -*- |
||||
"""mythril.py: Bug hunting on the Ethereum blockchain |
||||
|
||||
http://www.github.com/b-mueller/mythril |
||||
""" |
||||
|
||||
import codecs |
||||
import logging |
||||
import os |
||||
import platform |
||||
import re |
||||
import traceback |
||||
from pathlib import Path |
||||
from shutil import copyfile |
||||
from configparser import ConfigParser |
||||
|
||||
import solc |
||||
from ethereum import utils |
||||
from solc.exceptions import SolcError |
||||
|
||||
from mythril.ethereum import util |
||||
from mythril.ethereum.evmcontract import EVMContract |
||||
from mythril.ethereum.interface.rpc.client import EthJsonRpc |
||||
from mythril.ethereum.interface.rpc.exceptions import ConnectionError |
||||
from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file |
||||
from mythril.support import signatures |
||||
from mythril.support.source_support import Source |
||||
from mythril.support.loader import DynLoader |
||||
from mythril.exceptions import CompilerError, NoContractFoundError, CriticalError |
||||
from mythril.analysis.symbolic import SymExecWrapper |
||||
from mythril.analysis.callgraph import generate_graph |
||||
from mythril.analysis.traceexplore import get_serializable_statespace |
||||
from mythril.analysis.security import fire_lasers, retrieve_callback_issues |
||||
from mythril.analysis.report import Report |
||||
from mythril.support.truffle import analyze_truffle_project |
||||
from mythril.ethereum.interface.leveldb.client import EthLevelDB |
||||
from mythril.laser.smt import SolverStatistics |
||||
from mythril.support.start_time import StartTime |
||||
|
||||
|
||||
log = logging.getLogger(__name__) |
||||
|
||||
|
||||
class Mythril(object): |
||||
"""Mythril main interface class. |
||||
|
||||
1. create mythril object |
||||
2. set rpc or leveldb interface if needed |
||||
3. load contracts (from solidity, bytecode, address) |
||||
4. fire_lasers |
||||
|
||||
.. code-block:: python |
||||
|
||||
mythril = Mythril() |
||||
mythril.set_api_rpc_infura() |
||||
|
||||
# (optional) other API adapters |
||||
mythril.set_api_rpc(args) |
||||
mythril.set_api_rpc_localhost() |
||||
mythril.set_api_leveldb(path) |
||||
|
||||
# (optional) other func |
||||
mythril.analyze_truffle_project(args) |
||||
mythril.search_db(args) |
||||
|
||||
# load contract |
||||
mythril.load_from_bytecode(bytecode) |
||||
mythril.load_from_address(address) |
||||
mythril.load_from_solidity(solidity_file) |
||||
|
||||
# analyze |
||||
print(mythril.fire_lasers(args).as_text()) |
||||
|
||||
# (optional) graph |
||||
for contract in mythril.contracts: |
||||
# prints html or save it to file |
||||
print(mythril.graph_html(args)) |
||||
|
||||
# (optional) other funcs |
||||
mythril.dump_statespaces(args) |
||||
mythril.disassemble(contract) |
||||
mythril.get_state_variable_from_storage(args) |
||||
""" |
||||
|
||||
def __init__( |
||||
self, |
||||
solv=None, |
||||
solc_args=None, |
||||
dynld=False, |
||||
enable_online_lookup=False, |
||||
onchain_storage_access=True, |
||||
): |
||||
|
||||
self.solv = solv |
||||
self.solc_args = solc_args |
||||
self.dynld = dynld |
||||
self.onchain_storage_access = onchain_storage_access |
||||
self.enable_online_lookup = enable_online_lookup |
||||
|
||||
self.mythril_dir = self._init_mythril_dir() |
||||
|
||||
# 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") |
||||
self.leveldb_dir = self._init_config() |
||||
|
||||
self.eth = None # ethereum API client |
||||
self.eth_db = None # ethereum LevelDB client |
||||
|
||||
self.contracts = [] # loaded contracts |
||||
|
||||
@staticmethod |
||||
def _init_mythril_dir(): |
||||
try: |
||||
mythril_dir = os.environ["MYTHRIL_DIR"] |
||||
except KeyError: |
||||
mythril_dir = os.path.join(os.path.expanduser("~"), ".mythril") |
||||
|
||||
if not os.path.exists(mythril_dir): |
||||
# Initialize data directory |
||||
log.info("Creating mythril data directory") |
||||
os.mkdir(mythril_dir) |
||||
|
||||
db_path = str(Path(mythril_dir) / "signatures.db") |
||||
if not os.path.exists(db_path): |
||||
# if the default mythril dir doesn't contain a signature DB |
||||
# initialize it with the default one from the project root |
||||
asset_dir = Path(__file__).parent / "support" / "assets" |
||||
copyfile(str(asset_dir / "signatures.db"), db_path) |
||||
|
||||
return mythril_dir |
||||
|
||||
def _init_config(self): |
||||
"""If no config file exists, create it and add default options. |
||||
|
||||
Default LevelDB path is specified based on OS |
||||
dynamic loading is set to infura by default in the file |
||||
Returns: leveldb directory |
||||
""" |
||||
|
||||
system = platform.system().lower() |
||||
leveldb_fallback_dir = os.path.expanduser("~") |
||||
if system.startswith("darwin"): |
||||
leveldb_fallback_dir = os.path.join( |
||||
leveldb_fallback_dir, "Library", "Ethereum" |
||||
) |
||||
elif system.startswith("windows"): |
||||
leveldb_fallback_dir = os.path.join( |
||||
leveldb_fallback_dir, "AppData", "Roaming", "Ethereum" |
||||
) |
||||
else: |
||||
leveldb_fallback_dir = os.path.join(leveldb_fallback_dir, ".ethereum") |
||||
leveldb_fallback_dir = os.path.join(leveldb_fallback_dir, "geth", "chaindata") |
||||
|
||||
if not os.path.exists(self.config_path): |
||||
log.info("No config file found. Creating default: " + self.config_path) |
||||
open(self.config_path, "a").close() |
||||
|
||||
config = ConfigParser(allow_no_value=True) |
||||
config.optionxform = str |
||||
config.read(self.config_path, "utf-8") |
||||
if "defaults" not in config.sections(): |
||||
self._add_default_options(config) |
||||
|
||||
if not config.has_option("defaults", "leveldb_dir"): |
||||
self._add_leveldb_option(config, leveldb_fallback_dir) |
||||
|
||||
if not config.has_option("defaults", "dynamic_loading"): |
||||
self._add_dynamic_loading_option(config) |
||||
|
||||
with codecs.open(self.config_path, "w", "utf-8") as fp: |
||||
config.write(fp) |
||||
|
||||
leveldb_dir = config.get( |
||||
"defaults", "leveldb_dir", fallback=leveldb_fallback_dir |
||||
) |
||||
return os.path.expanduser(leveldb_dir) |
||||
|
||||
@staticmethod |
||||
def _add_default_options(config): |
||||
config.add_section("defaults") |
||||
|
||||
@staticmethod |
||||
def _add_leveldb_option(config, leveldb_fallback_dir): |
||||
config.set("defaults", "#Default chaindata locations:") |
||||
config.set("defaults", "#– Mac: ~/Library/Ethereum/geth/chaindata") |
||||
config.set("defaults", "#– Linux: ~/.ethereum/geth/chaindata") |
||||
config.set( |
||||
"defaults", |
||||
"#– Windows: %USERPROFILE%\\AppData\\Roaming\\Ethereum\\geth\\chaindata", |
||||
) |
||||
config.set("defaults", "leveldb_dir", leveldb_fallback_dir) |
||||
|
||||
@staticmethod |
||||
def _add_dynamic_loading_option(config): |
||||
config.set("defaults", "#– To connect to Infura use dynamic_loading: infura") |
||||
config.set( |
||||
"defaults", |
||||
"#– To connect to Rpc use " |
||||
"dynamic_loading: HOST:PORT / ganache / infura-[network_name]", |
||||
) |
||||
config.set( |
||||
"defaults", "#– To connect to local host use dynamic_loading: localhost" |
||||
) |
||||
config.set("defaults", "dynamic_loading", "infura") |
||||
|
||||
def analyze_truffle_project(self, *args, **kwargs): |
||||
""" |
||||
|
||||
:param args: |
||||
:param kwargs: |
||||
:return: |
||||
""" |
||||
return analyze_truffle_project( |
||||
self.sigs, *args, **kwargs |
||||
) # just passthru by passing signatures for now |
||||
|
||||
@staticmethod |
||||
def _init_solc_binary(version): |
||||
"""Figure out solc binary and version. |
||||
|
||||
Only proper versions are supported. No nightlies, commits etc (such as available in remix). |
||||
""" |
||||
|
||||
if not version: |
||||
return os.environ.get("SOLC") or "solc" |
||||
|
||||
# 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: |
||||
log.info("Given version matches installed version") |
||||
solc_binary = os.environ.get("SOLC") or "solc" |
||||
else: |
||||
solc_binary = util.solc_exists(version) |
||||
if solc_binary: |
||||
log.info("Given version is already installed") |
||||
else: |
||||
try: |
||||
solc.install_solc("v" + version) |
||||
solc_binary = util.solc_exists(version) |
||||
if not solc_binary: |
||||
raise SolcError() |
||||
except SolcError: |
||||
raise CriticalError( |
||||
"There was an error when trying to install the specified solc version" |
||||
) |
||||
|
||||
log.info("Setting the compiler to %s", solc_binary) |
||||
|
||||
return solc_binary |
||||
|
||||
def set_api_leveldb(self, leveldb): |
||||
""" |
||||
|
||||
:param leveldb: |
||||
:return: |
||||
""" |
||||
self.eth_db = EthLevelDB(leveldb) |
||||
self.eth = self.eth_db |
||||
return self.eth |
||||
|
||||
def set_api_rpc_infura(self): |
||||
"""Set the RPC mode to INFURA on mainnet.""" |
||||
self.eth = EthJsonRpc("mainnet.infura.io", 443, True) |
||||
log.info("Using INFURA for RPC queries") |
||||
|
||||
def set_api_rpc(self, rpc=None, rpctls=False): |
||||
""" |
||||
|
||||
:param rpc: |
||||
:param rpctls: |
||||
""" |
||||
if rpc == "ganache": |
||||
rpcconfig = ("localhost", 8545, False) |
||||
else: |
||||
m = re.match(r"infura-(.*)", rpc) |
||||
if m and m.group(1) in ["mainnet", "rinkeby", "kovan", "ropsten"]: |
||||
rpcconfig = (m.group(1) + ".infura.io", 443, True) |
||||
else: |
||||
try: |
||||
host, port = rpc.split(":") |
||||
rpcconfig = (host, int(port), rpctls) |
||||
except ValueError: |
||||
raise CriticalError( |
||||
"Invalid RPC argument, use 'ganache', 'infura-[network]' or 'HOST:PORT'" |
||||
) |
||||
|
||||
if rpcconfig: |
||||
self.eth = EthJsonRpc(rpcconfig[0], int(rpcconfig[1]), rpcconfig[2]) |
||||
log.info("Using RPC settings: %s" % str(rpcconfig)) |
||||
else: |
||||
raise CriticalError("Invalid RPC settings, check help for details.") |
||||
|
||||
def set_api_rpc_localhost(self): |
||||
"""Set the RPC mode to a local instance.""" |
||||
self.eth = EthJsonRpc("localhost", 8545) |
||||
log.info("Using default RPC settings: http://localhost:8545") |
||||
|
||||
def set_api_from_config_path(self): |
||||
"""Set the RPC mode based on a given config file.""" |
||||
config = ConfigParser(allow_no_value=False) |
||||
config.optionxform = str |
||||
config.read(self.config_path, "utf-8") |
||||
if config.has_option("defaults", "dynamic_loading"): |
||||
dynamic_loading = config.get("defaults", "dynamic_loading") |
||||
else: |
||||
dynamic_loading = "infura" |
||||
if dynamic_loading == "infura": |
||||
self.set_api_rpc_infura() |
||||
elif dynamic_loading == "localhost": |
||||
self.set_api_rpc_localhost() |
||||
else: |
||||
self.set_api_rpc(dynamic_loading) |
||||
|
||||
def search_db(self, search): |
||||
""" |
||||
|
||||
:param search: |
||||
""" |
||||
|
||||
def search_callback(_, address, balance): |
||||
""" |
||||
|
||||
:param _: |
||||
:param address: |
||||
:param balance: |
||||
""" |
||||
print("Address: " + address + ", balance: " + str(balance)) |
||||
|
||||
try: |
||||
self.eth_db.search(search, search_callback) |
||||
|
||||
except SyntaxError: |
||||
raise CriticalError("Syntax error in search expression.") |
||||
|
||||
def contract_hash_to_address(self, hash): |
||||
""" |
||||
|
||||
:param hash: |
||||
""" |
||||
if not re.match(r"0x[a-fA-F0-9]{64}", hash): |
||||
raise CriticalError("Invalid address hash. Expected format is '0x...'.") |
||||
|
||||
print(self.eth_db.contract_hash_to_address(hash)) |
||||
|
||||
def load_from_bytecode(self, code, bin_runtime=False, address=None): |
||||
""" |
||||
|
||||
:param code: |
||||
:param bin_runtime: |
||||
:param address: |
||||
:return: |
||||
""" |
||||
if address is None: |
||||
address = util.get_indexed_address(0) |
||||
if bin_runtime: |
||||
self.contracts.append( |
||||
EVMContract( |
||||
code=code, |
||||
name="MAIN", |
||||
enable_online_lookup=self.enable_online_lookup, |
||||
) |
||||
) |
||||
else: |
||||
self.contracts.append( |
||||
EVMContract( |
||||
creation_code=code, |
||||
name="MAIN", |
||||
enable_online_lookup=self.enable_online_lookup, |
||||
) |
||||
) |
||||
return address, self.contracts[-1] # return address and contract object |
||||
|
||||
def load_from_address(self, address): |
||||
""" |
||||
|
||||
:param address: |
||||
:return: |
||||
""" |
||||
if not re.match(r"0x[a-fA-F0-9]{40}", address): |
||||
raise CriticalError("Invalid contract address. Expected format is '0x...'.") |
||||
|
||||
try: |
||||
code = self.eth.eth_getCode(address) |
||||
except FileNotFoundError as e: |
||||
raise CriticalError("IPC error: " + str(e)) |
||||
except ConnectionError: |
||||
raise CriticalError( |
||||
"Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly." |
||||
) |
||||
except Exception as e: |
||||
raise CriticalError("IPC / RPC error: " + str(e)) |
||||
else: |
||||
if code == "0x" or code == "0x0": |
||||
raise CriticalError( |
||||
"Received an empty response from eth_getCode. Check the contract address and verify that you are on the correct chain." |
||||
) |
||||
else: |
||||
self.contracts.append( |
||||
EVMContract( |
||||
code, |
||||
name=address, |
||||
enable_online_lookup=self.enable_online_lookup, |
||||
) |
||||
) |
||||
return address, self.contracts[-1] # return address and contract object |
||||
|
||||
def load_from_solidity(self, solidity_files): |
||||
""" |
||||
|
||||
:param solidity_files: |
||||
:return: |
||||
""" |
||||
address = util.get_indexed_address(0) |
||||
contracts = [] |
||||
for file in solidity_files: |
||||
if ":" in file: |
||||
file, contract_name = file.split(":") |
||||
else: |
||||
contract_name = None |
||||
|
||||
file = os.path.expanduser(file) |
||||
|
||||
try: |
||||
# import signatures from solidity source |
||||
self.sigs.import_solidity_file( |
||||
file, solc_binary=self.solc_binary, solc_args=self.solc_args |
||||
) |
||||
if contract_name is not None: |
||||
contract = SolidityContract( |
||||
input_file=file, |
||||
name=contract_name, |
||||
solc_args=self.solc_args, |
||||
solc_binary=self.solc_binary, |
||||
) |
||||
self.contracts.append(contract) |
||||
contracts.append(contract) |
||||
else: |
||||
for contract in get_contracts_from_file( |
||||
input_file=file, |
||||
solc_args=self.solc_args, |
||||
solc_binary=self.solc_binary, |
||||
): |
||||
self.contracts.append(contract) |
||||
contracts.append(contract) |
||||
|
||||
except FileNotFoundError: |
||||
raise CriticalError("Input file not found: " + file) |
||||
except CompilerError as e: |
||||
raise CriticalError(e) |
||||
except NoContractFoundError: |
||||
log.error( |
||||
"The file " + file + " does not contain a compilable contract." |
||||
) |
||||
|
||||
return address, contracts |
||||
|
||||
def dump_statespace( |
||||
self, |
||||
strategy, |
||||
contract, |
||||
address=None, |
||||
max_depth=None, |
||||
execution_timeout=None, |
||||
create_timeout=None, |
||||
enable_iprof=False, |
||||
): |
||||
""" |
||||
|
||||
:param strategy: |
||||
:param contract: |
||||
:param address: |
||||
:param max_depth: |
||||
:param execution_timeout: |
||||
:param create_timeout: |
||||
:return: |
||||
""" |
||||
sym = SymExecWrapper( |
||||
contract, |
||||
address, |
||||
strategy, |
||||
dynloader=DynLoader( |
||||
self.eth, |
||||
storage_loading=self.onchain_storage_access, |
||||
contract_loading=self.dynld, |
||||
), |
||||
max_depth=max_depth, |
||||
execution_timeout=execution_timeout, |
||||
create_timeout=create_timeout, |
||||
enable_iprof=enable_iprof, |
||||
) |
||||
|
||||
return get_serializable_statespace(sym) |
||||
|
||||
def graph_html( |
||||
self, |
||||
strategy, |
||||
contract, |
||||
address, |
||||
max_depth=None, |
||||
enable_physics=False, |
||||
phrackify=False, |
||||
execution_timeout=None, |
||||
create_timeout=None, |
||||
enable_iprof=False, |
||||
): |
||||
""" |
||||
|
||||
:param strategy: |
||||
:param contract: |
||||
:param address: |
||||
:param max_depth: |
||||
:param enable_physics: |
||||
:param phrackify: |
||||
:param execution_timeout: |
||||
:param create_timeout: |
||||
:return: |
||||
""" |
||||
sym = SymExecWrapper( |
||||
contract, |
||||
address, |
||||
strategy, |
||||
dynloader=DynLoader( |
||||
self.eth, |
||||
storage_loading=self.onchain_storage_access, |
||||
contract_loading=self.dynld, |
||||
), |
||||
max_depth=max_depth, |
||||
execution_timeout=execution_timeout, |
||||
create_timeout=create_timeout, |
||||
enable_iprof=enable_iprof, |
||||
) |
||||
return generate_graph(sym, physics=enable_physics, phrackify=phrackify) |
||||
|
||||
def fire_lasers( |
||||
self, |
||||
strategy, |
||||
contracts=None, |
||||
address=None, |
||||
modules=None, |
||||
verbose_report=False, |
||||
max_depth=None, |
||||
execution_timeout=None, |
||||
create_timeout=None, |
||||
transaction_count=None, |
||||
enable_iprof=False, |
||||
): |
||||
""" |
||||
|
||||
:param strategy: |
||||
:param contracts: |
||||
:param address: |
||||
:param modules: |
||||
:param verbose_report: |
||||
:param max_depth: |
||||
:param execution_timeout: |
||||
:param create_timeout: |
||||
:param transaction_count: |
||||
:return: |
||||
""" |
||||
all_issues = [] |
||||
SolverStatistics().enabled = True |
||||
exceptions = [] |
||||
for contract in contracts or self.contracts: |
||||
StartTime() # Reinitialize start time for new contracts |
||||
try: |
||||
sym = SymExecWrapper( |
||||
contract, |
||||
address, |
||||
strategy, |
||||
dynloader=DynLoader( |
||||
self.eth, |
||||
storage_loading=self.onchain_storage_access, |
||||
contract_loading=self.dynld, |
||||
), |
||||
max_depth=max_depth, |
||||
execution_timeout=execution_timeout, |
||||
create_timeout=create_timeout, |
||||
transaction_count=transaction_count, |
||||
modules=modules, |
||||
compulsory_statespace=False, |
||||
enable_iprof=enable_iprof, |
||||
) |
||||
issues = fire_lasers(sym, modules) |
||||
except KeyboardInterrupt: |
||||
log.critical("Keyboard Interrupt") |
||||
issues = retrieve_callback_issues(modules) |
||||
except Exception: |
||||
log.critical( |
||||
"Exception occurred, aborting analysis. Please report this issue to the Mythril GitHub page.\n" |
||||
+ traceback.format_exc() |
||||
) |
||||
issues = retrieve_callback_issues(modules) |
||||
exceptions.append(traceback.format_exc()) |
||||
for issue in issues: |
||||
issue.add_code_info(contract) |
||||
|
||||
all_issues += issues |
||||
log.info("Solver statistics: \n{}".format(str(SolverStatistics()))) |
||||
|
||||
source_data = Source() |
||||
source_data.get_source_from_contracts_list(self.contracts) |
||||
# Finally, output the results |
||||
report = Report(verbose_report, source_data, exceptions=exceptions) |
||||
for issue in all_issues: |
||||
report.append_issue(issue) |
||||
|
||||
return report |
||||
|
||||
def get_state_variable_from_storage(self, address, params=None): |
||||
""" |
||||
|
||||
:param address: |
||||
:param params: |
||||
:return: |
||||
""" |
||||
if params is None: |
||||
params = [] |
||||
(position, length, mappings) = (0, 1, []) |
||||
try: |
||||
if params[0] == "mapping": |
||||
if len(params) < 3: |
||||
raise CriticalError("Invalid number of parameters.") |
||||
position = int(params[1]) |
||||
position_formatted = utils.zpad(utils.int_to_big_endian(position), 32) |
||||
for i in range(2, len(params)): |
||||
key = bytes(params[i], "utf8") |
||||
key_formatted = utils.rzpad(key, 32) |
||||
mappings.append( |
||||
int.from_bytes( |
||||
utils.sha3(key_formatted + position_formatted), |
||||
byteorder="big", |
||||
) |
||||
) |
||||
|
||||
length = len(mappings) |
||||
if length == 1: |
||||
position = mappings[0] |
||||
|
||||
else: |
||||
if len(params) >= 4: |
||||
raise CriticalError("Invalid number of parameters.") |
||||
|
||||
if len(params) >= 1: |
||||
position = int(params[0]) |
||||
if len(params) >= 2: |
||||
length = int(params[1]) |
||||
if len(params) == 3 and params[2] == "array": |
||||
position_formatted = utils.zpad( |
||||
utils.int_to_big_endian(position), 32 |
||||
) |
||||
position = int.from_bytes( |
||||
utils.sha3(position_formatted), byteorder="big" |
||||
) |
||||
|
||||
except ValueError: |
||||
raise CriticalError( |
||||
"Invalid storage index. Please provide a numeric value." |
||||
) |
||||
|
||||
outtxt = [] |
||||
|
||||
try: |
||||
if length == 1: |
||||
outtxt.append( |
||||
"{}: {}".format( |
||||
position, self.eth.eth_getStorageAt(address, position) |
||||
) |
||||
) |
||||
else: |
||||
if len(mappings) > 0: |
||||
for i in range(0, len(mappings)): |
||||
position = mappings[i] |
||||
outtxt.append( |
||||
"{}: {}".format( |
||||
hex(position), |
||||
self.eth.eth_getStorageAt(address, position), |
||||
) |
||||
) |
||||
else: |
||||
for i in range(position, position + length): |
||||
outtxt.append( |
||||
"{}: {}".format( |
||||
hex(i), self.eth.eth_getStorageAt(address, i) |
||||
) |
||||
) |
||||
except FileNotFoundError as e: |
||||
raise CriticalError("IPC error: " + str(e)) |
||||
except ConnectionError: |
||||
raise CriticalError( |
||||
"Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly." |
||||
) |
||||
return "\n".join(outtxt) |
||||
|
||||
@staticmethod |
||||
def disassemble(contract): |
||||
""" |
||||
|
||||
:param contract: |
||||
:return: |
||||
""" |
||||
return contract.get_easm() |
||||
|
||||
@staticmethod |
||||
def hash_for_function_signature(sig): |
||||
""" |
||||
|
||||
:param sig: |
||||
:return: |
||||
""" |
||||
return "0x%s" % utils.sha3(sig)[:4].hex() |
@ -0,0 +1,94 @@ |
||||
# This pyethereum opcodes file with added opcodes |
||||
from typing import Dict, Tuple |
||||
|
||||
opcodes = { |
||||
0x00: ("STOP", 0, 0, 0), |
||||
0x01: ("ADD", 2, 1, 3), |
||||
0x02: ("MUL", 2, 1, 5), |
||||
0x03: ("SUB", 2, 1, 3), |
||||
0x04: ("DIV", 2, 1, 5), |
||||
0x05: ("SDIV", 2, 1, 5), |
||||
0x06: ("MOD", 2, 1, 5), |
||||
0x07: ("SMOD", 2, 1, 5), |
||||
0x08: ("ADDMOD", 3, 1, 8), |
||||
0x09: ("MULMOD", 3, 1, 8), |
||||
0x0A: ("EXP", 2, 1, 10), |
||||
0x0B: ("SIGNEXTEND", 2, 1, 5), |
||||
0x10: ("LT", 2, 1, 3), |
||||
0x11: ("GT", 2, 1, 3), |
||||
0x12: ("SLT", 2, 1, 3), |
||||
0x13: ("SGT", 2, 1, 3), |
||||
0x14: ("EQ", 2, 1, 3), |
||||
0x15: ("ISZERO", 1, 1, 3), |
||||
0x16: ("AND", 2, 1, 3), |
||||
0x17: ("OR", 2, 1, 3), |
||||
0x18: ("XOR", 2, 1, 3), |
||||
0x19: ("NOT", 1, 1, 3), |
||||
0x1A: ("BYTE", 2, 1, 3), |
||||
0x1B: ("SHL", 2, 1, 3), |
||||
0x1C: ("SHR", 2, 1, 3), |
||||
0x1D: ("SAR", 2, 1, 3), |
||||
0x20: ("SHA3", 2, 1, 30), |
||||
0x30: ("ADDRESS", 0, 1, 2), |
||||
0x31: ("BALANCE", 1, 1, 20), # now 400 |
||||
0x32: ("ORIGIN", 0, 1, 2), |
||||
0x33: ("CALLER", 0, 1, 2), |
||||
0x34: ("CALLVALUE", 0, 1, 2), |
||||
0x35: ("CALLDATALOAD", 1, 1, 3), |
||||
0x36: ("CALLDATASIZE", 0, 1, 2), |
||||
0x37: ("CALLDATACOPY", 3, 0, 3), |
||||
0x38: ("CODESIZE", 0, 1, 2), |
||||
0x39: ("CODECOPY", 3, 0, 3), |
||||
0x3A: ("GASPRICE", 0, 1, 2), |
||||
0x3B: ("EXTCODESIZE", 1, 1, 20), # now 700 |
||||
0x3C: ("EXTCODECOPY", 4, 0, 20), # now 700 |
||||
0x3D: ("RETURNDATASIZE", 0, 1, 2), |
||||
0x3E: ("RETURNDATACOPY", 3, 0, 3), |
||||
0x3F: ("EXTCODEHASH", 3, 0, 3), |
||||
0x40: ("BLOCKHASH", 1, 1, 20), |
||||
0x41: ("COINBASE", 0, 1, 2), |
||||
0x42: ("TIMESTAMP", 0, 1, 2), |
||||
0x43: ("NUMBER", 0, 1, 2), |
||||
0x44: ("DIFFICULTY", 0, 1, 2), |
||||
0x45: ("GASLIMIT", 0, 1, 2), |
||||
0x50: ("POP", 1, 0, 2), |
||||
0x51: ("MLOAD", 1, 1, 3), |
||||
0x52: ("MSTORE", 2, 0, 3), |
||||
0x53: ("MSTORE8", 2, 0, 3), |
||||
0x54: ("SLOAD", 1, 1, 50), # 200 now |
||||
0x55: ("SSTORE", 2, 0, 0), |
||||
0x56: ("JUMP", 1, 0, 8), |
||||
0x57: ("JUMPI", 2, 0, 10), |
||||
0x58: ("PC", 0, 1, 2), |
||||
0x59: ("MSIZE", 0, 1, 2), |
||||
0x5A: ("GAS", 0, 1, 2), |
||||
0x5B: ("JUMPDEST", 0, 0, 1), |
||||
0xA0: ("LOG0", 2, 0, 375), |
||||
0xA1: ("LOG1", 3, 0, 750), |
||||
0xA2: ("LOG2", 4, 0, 1125), |
||||
0xA3: ("LOG3", 5, 0, 1500), |
||||
0xA4: ("LOG4", 6, 0, 1875), |
||||
0xF0: ("CREATE", 3, 1, 32000), |
||||
0xF1: ("CALL", 7, 1, 40), # 700 now |
||||
0xF2: ("CALLCODE", 7, 1, 40), # 700 now |
||||
0xF3: ("RETURN", 2, 0, 0), |
||||
0xF4: ("DELEGATECALL", 6, 1, 40), # 700 now |
||||
0xF5: ("CREATE2", 3, 1, 32000), |
||||
0xFA: ("STATICCALL", 6, 1, 40), |
||||
0xFD: ("REVERT", 2, 0, 0), |
||||
0xFF: ("SUICIDE", 1, 0, 0), # 5000 now |
||||
} # type: Dict[int, Tuple[str, int, int, int]] |
||||
|
||||
opcodesMetropolis = {0x3D, 0x3E, 0xFA, 0xFD} |
||||
|
||||
for i in range(1, 33): |
||||
opcodes[0x5F + i] = ("PUSH" + str(i), 0, 1, 3) |
||||
|
||||
for i in range(1, 17): |
||||
opcodes[0x7F + i] = ("DUP" + str(i), i, i + 1, 3) |
||||
opcodes[0x8F + i] = ("SWAP" + str(i), i + 1, i + 1, 3) |
||||
|
||||
reverse_opcodes = {} |
||||
for o in opcodes: |
||||
vars()[opcodes[o][0]] = opcodes[o] |
||||
reverse_opcodes[opcodes[o][0]] = o |
@ -0,0 +1,9 @@ |
||||
from time import time |
||||
from mythril.support.support_utils import Singleton |
||||
|
||||
|
||||
class StartTime(metaclass=Singleton): |
||||
"""Maintains the start time of the current contract in execution""" |
||||
|
||||
def __init__(self): |
||||
self.global_start_time = time() |
@ -0,0 +1,148 @@ |
||||
import pytest |
||||
|
||||
from mythril.disassembler.disassembly import Disassembly |
||||
from mythril.laser.ethereum.state.environment import Environment |
||||
from mythril.laser.ethereum.state.account import Account |
||||
from mythril.laser.ethereum.state.machine_state import MachineState |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
from mythril.laser.ethereum.state.world_state import WorldState |
||||
from mythril.laser.ethereum.instructions import Instruction |
||||
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction |
||||
from mythril.laser.smt import symbol_factory, simplify |
||||
|
||||
|
||||
def get_state(): |
||||
active_account = Account("0x0", code=Disassembly("60606040")) |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) |
||||
state.transaction_stack.append( |
||||
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) |
||||
) |
||||
return state |
||||
|
||||
|
||||
BVV = symbol_factory.BitVecVal |
||||
BV = symbol_factory.BitVecSym |
||||
|
||||
test_data = ( |
||||
([BVV(-1, 256), BVV(1, 256)], BVV(-1, 256)), |
||||
([BVV(23, 256), BVV(257, 256)], BVV(0, 256)), |
||||
([BVV(23, 256), BVV(30, 256)], BVV(23 >> 30, 256)), |
||||
([BVV(-10, 256), BVV(10, 256)], BVV(-1, 256)), |
||||
([BV("a", 256), BV("b", 256)], BV("a", 256) >> BV("b", 256)), |
||||
) |
||||
|
||||
|
||||
@pytest.mark.parametrize("inputs,output", test_data) |
||||
def test_sar(inputs, output): |
||||
# Arrange |
||||
state = get_state() |
||||
|
||||
state.mstate.stack = inputs |
||||
instruction = Instruction("sar", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == output |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
# Test cases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right |
||||
"val1, val2, expected ", |
||||
( |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x00", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x01", |
||||
"0xc000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0xff", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x0100", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x0101", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x00", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x01", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xff", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x0100", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x4000000000000000000000000000000000000000000000000000000000000000", |
||||
"0xfe", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xf8", |
||||
"0x000000000000000000000000000000000000000000000000000000000000007f", |
||||
), |
||||
( |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xfe", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xff", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x0100", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
), |
||||
) |
||||
def test_concrete_sar(val1, val2, expected): |
||||
# Arrange |
||||
state = get_state() |
||||
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)] |
||||
expected = BVV(int(expected, 16), 256) |
||||
instruction = Instruction("sar", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == expected |
@ -0,0 +1,123 @@ |
||||
import pytest |
||||
|
||||
from mythril.disassembler.disassembly import Disassembly |
||||
from mythril.laser.ethereum.state.environment import Environment |
||||
from mythril.laser.ethereum.state.account import Account |
||||
from mythril.laser.ethereum.state.machine_state import MachineState |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
from mythril.laser.ethereum.state.world_state import WorldState |
||||
from mythril.laser.ethereum.instructions import Instruction |
||||
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction |
||||
from mythril.laser.smt import symbol_factory, simplify |
||||
|
||||
|
||||
def get_state(): |
||||
active_account = Account("0x0", code=Disassembly("60606040")) |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) |
||||
state.transaction_stack.append( |
||||
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) |
||||
) |
||||
return state |
||||
|
||||
|
||||
BVV = symbol_factory.BitVecVal |
||||
BV = symbol_factory.BitVecSym |
||||
|
||||
test_data = ( |
||||
([BVV(2, 256), BVV(2, 256)], BVV(8, 256)), |
||||
([BVV(23, 256), BVV(257, 256)], BVV(0, 256)), |
||||
([BVV(23, 256), BVV(30, 256)], BVV(23 * (1 << 30), 256)), |
||||
([BV("a", 256), BVV(270, 256)], 0), |
||||
([BV("a", 256), BV("b", 256)], BV("a", 256) << BV("b", 256)), |
||||
) |
||||
|
||||
|
||||
@pytest.mark.parametrize("inputs,output,", test_data) |
||||
def test_shl(inputs, output): |
||||
# Arrange |
||||
state = get_state() |
||||
|
||||
state.mstate.stack = inputs |
||||
instruction = Instruction("shl", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == output |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
# Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left |
||||
"val1, val2, expected", |
||||
( |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x00", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000002", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0xff", |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x0100", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x0101", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x00", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x01", |
||||
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xff", |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x0100", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x01", |
||||
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", |
||||
), |
||||
), |
||||
) |
||||
def test_concrete_shl(val1, val2, expected): |
||||
# Arrange |
||||
state = get_state() |
||||
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)] |
||||
expected = BVV(int(expected, 16), 256) |
||||
instruction = Instruction("shl", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == expected |
@ -0,0 +1,125 @@ |
||||
import pytest |
||||
|
||||
from mythril.disassembler.disassembly import Disassembly |
||||
from mythril.laser.ethereum.state.environment import Environment |
||||
from mythril.laser.ethereum.state.account import Account |
||||
from mythril.laser.ethereum.state.machine_state import MachineState |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
from mythril.laser.ethereum.state.world_state import WorldState |
||||
from mythril.laser.ethereum.instructions import Instruction |
||||
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction |
||||
from mythril.laser.smt import symbol_factory, simplify, LShR |
||||
|
||||
|
||||
def get_state(): |
||||
active_account = Account("0x0", code=Disassembly("60606040")) |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) |
||||
state.transaction_stack.append( |
||||
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) |
||||
) |
||||
return state |
||||
|
||||
|
||||
BVV = symbol_factory.BitVecVal |
||||
BV = symbol_factory.BitVecSym |
||||
|
||||
test_data = ( |
||||
([BVV(33, 256), BVV(4, 256)], BVV(2, 256)), |
||||
([BVV(1 << 100, 256), BVV(257, 256)], BVV(0, 256)), |
||||
([BVV(23233, 256), BVV(10, 256)], BVV(23233 // (1 << 10), 256)), |
||||
([BV("a", 256), BVV(270, 256)], 0), |
||||
( |
||||
[BV("a", 256), BV("b", 256)], |
||||
LShR(BV("a", 256), BV("b", 256)), |
||||
), # Current approximate specs |
||||
) |
||||
|
||||
|
||||
@pytest.mark.parametrize("inputs,output,", test_data) |
||||
def test_shr(inputs, output): |
||||
# Arrange |
||||
state = get_state() |
||||
|
||||
state.mstate.stack = inputs |
||||
instruction = Instruction("shr", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == output |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
# Cases: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right |
||||
"val1, val2, expected", |
||||
( |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x00", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x01", |
||||
"0x4000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0xff", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x0100", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x8000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x0101", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x00", |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x01", |
||||
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0xff", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
||||
), |
||||
( |
||||
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
||||
"0x0100", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
( |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
"0x01", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
), |
||||
), |
||||
) |
||||
def test_concrete_shr(val1, val2, expected): |
||||
state = get_state() |
||||
state.mstate.stack = [BVV(int(val1, 16), 256), BVV(int(val2, 16), 256)] |
||||
expected = BVV(int(expected, 16), 256) |
||||
instruction = Instruction("shr", dynamic_loader=None) |
||||
|
||||
# Act |
||||
new_state = instruction.evaluate(state)[0] |
||||
|
||||
# Assert |
||||
assert simplify(new_state.mstate.stack[-1]) == expected |
@ -0,0 +1,82 @@ |
||||
from mythril.laser.smt import Solver, symbol_factory, bitvec |
||||
import z3 |
||||
import pytest |
||||
|
||||
import operator |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
"operation,expected", |
||||
[ |
||||
(operator.add, z3.unsat), |
||||
(operator.sub, z3.unsat), |
||||
(operator.and_, z3.sat), |
||||
(operator.or_, z3.sat), |
||||
(operator.xor, z3.unsat), |
||||
], |
||||
) |
||||
def test_bitvecfunc_arithmetic(operation, expected): |
||||
# Arrange |
||||
s = Solver() |
||||
|
||||
input_ = symbol_factory.BitVecVal(1, 8) |
||||
bvf = symbol_factory.BitVecFuncSym("bvf", "sha3", 256, input_=input_) |
||||
|
||||
x = symbol_factory.BitVecSym("x", 256) |
||||
y = symbol_factory.BitVecSym("y", 256) |
||||
|
||||
# Act |
||||
s.add(x != y) |
||||
s.add(operation(bvf, x) == operation(y, bvf)) |
||||
|
||||
# Assert |
||||
assert s.check() == expected |
||||
|
||||
|
||||
@pytest.mark.parametrize( |
||||
"operation,expected", |
||||
[ |
||||
(operator.eq, z3.sat), |
||||
(operator.ne, z3.unsat), |
||||
(operator.lt, z3.unsat), |
||||
(operator.le, z3.sat), |
||||
(operator.gt, z3.unsat), |
||||
(operator.ge, z3.sat), |
||||
(bitvec.UGT, z3.unsat), |
||||
(bitvec.UGE, z3.sat), |
||||
(bitvec.ULT, z3.unsat), |
||||
(bitvec.ULE, z3.sat), |
||||
], |
||||
) |
||||
def test_bitvecfunc_bitvecfunc_comparison(operation, expected): |
||||
# Arrange |
||||
s = Solver() |
||||
|
||||
input1 = symbol_factory.BitVecSym("input1", 256) |
||||
input2 = symbol_factory.BitVecSym("input2", 256) |
||||
bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1) |
||||
bvf2 = symbol_factory.BitVecFuncSym("bvf2", "sha3", 256, input_=input2) |
||||
|
||||
# Act |
||||
s.add(operation(bvf1, bvf2)) |
||||
s.add(input1 == input2) |
||||
|
||||
# Assert |
||||
assert s.check() == expected |
||||
|
||||
|
||||
def test_bitvecfunc_bitvecfuncval_comparison(): |
||||
# Arrange |
||||
s = Solver() |
||||
|
||||
input1 = symbol_factory.BitVecSym("input1", 256) |
||||
input2 = symbol_factory.BitVecVal(1337, 256) |
||||
bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1) |
||||
bvf2 = symbol_factory.BitVecFuncVal(12345678910, "sha3", 256, input_=input2) |
||||
|
||||
# Act |
||||
s.add(bvf1 == bvf2) |
||||
|
||||
# Assert |
||||
assert s.check() == z3.sat |
||||
assert s.model().eval(input2.raw) == 1337 |
@ -1 +1,110 @@ |
||||
{"error": null, "issues": [{"address": 661, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "function": "thisisfine()", "max_gas_used": 1254, "min_gas_used": 643, "severity": "Low", "sourceMap": null, "swc-id": "107", "title": "External Call To Fixed Address"}, {"address": 661, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "thisisfine()", "max_gas_used": 35972, "min_gas_used": 1361, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "function": "callstoredaddress()", "max_gas_used": 1298, "min_gas_used": 687, "severity": "Low", "sourceMap": null, "swc-id": "107", "title": "External Call To Fixed Address"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "callstoredaddress()", "max_gas_used": 36016, "min_gas_used": 1405, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}, {"address": 858, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "function": "reentrancy()", "max_gas_used": 1320, "min_gas_used": 709, "severity": "Low", "sourceMap": null, "swc-id": "107", "title": "External Call To Fixed Address"}, {"address": 858, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "reentrancy()", "max_gas_used": 61052, "min_gas_used": 6441, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}, {"address": 912, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on thecontract state.", "function": "calluseraddress(address)", "max_gas_used": 616, "min_gas_used": 335, "severity": "Medium", "sourceMap": null, "swc-id": "107", "title": "External Call To User-Supplied Address"}, {"address": 912, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "calluseraddress(address)", "max_gas_used": 35336, "min_gas_used": 1055, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 661, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", |
||||
"function": "thisisfine()", |
||||
"max_gas_used": 1254, |
||||
"min_gas_used": 643, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To Fixed Address" |
||||
}, |
||||
{ |
||||
"address": 661, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "thisisfine()", |
||||
"max_gas_used": 35972, |
||||
"min_gas_used": 1361, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", |
||||
"function": "callstoredaddress()", |
||||
"max_gas_used": 1298, |
||||
"min_gas_used": 687, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To Fixed Address" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "callstoredaddress()", |
||||
"max_gas_used": 36016, |
||||
"min_gas_used": 1405, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"address": 858, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", |
||||
"function": "reentrancy()", |
||||
"max_gas_used": 1320, |
||||
"min_gas_used": 709, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To Fixed Address" |
||||
}, |
||||
{ |
||||
"address": 858, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "reentrancy()", |
||||
"max_gas_used": 61052, |
||||
"min_gas_used": 6441, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"address": 912, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state.", |
||||
"function": "calluseraddress(address)", |
||||
"max_gas_used": 616, |
||||
"min_gas_used": 335, |
||||
"severity": "Medium", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To User-Supplied Address" |
||||
}, |
||||
{ |
||||
"address": 912, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "calluseraddress(address)", |
||||
"max_gas_used": 35336, |
||||
"min_gas_used": 1055, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,132 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "The contract executes an external message call.", |
||||
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "661:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The contract executes an external message call.", |
||||
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "779:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The contract executes an external message call.", |
||||
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "858:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "A call to a user-supplied address is executed.", |
||||
"tail": "The callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on thecontract state." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "912:1:0" |
||||
} |
||||
], |
||||
"severity": "Medium", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "661:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "779:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "858:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "912:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0x7cbb77986c6b1bf6e945cd3fba06d3ea3d28cfc49cdfdc9571ec30703ac5862f" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "661:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "779:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "858:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "A call to a user-supplied address is executed.", "tail": "The callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state."}, "extra": {}, "locations": [{"sourceMap": "912:1:0"}], "severity": "Medium", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "661:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "779:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "858:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "912:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x7cbb77986c6b1bf6e945cd3fba06d3ea3d28cfc49cdfdc9571ec30703ac5862f"], "sourceType": "raw-bytecode"}] |
@ -1 +1,5 @@ |
||||
{"error": null, "issues": [], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [], |
||||
"success": true |
||||
} |
@ -1,9 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": [], "sourceType": "raw-bytecode"}] |
@ -1 +1,58 @@ |
||||
{"error": null, "issues": [{"address": 446, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", "function": "assert3(uint256)", "max_gas_used": 301, "min_gas_used": 206, "severity": "Low", "sourceMap": null, "swc-id": "110", "title": "Exception State"}, {"address": 484, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", "function": "arrayaccess(uint256)", "max_gas_used": 351, "min_gas_used": 256, "severity": "Low", "sourceMap": null, "swc-id": "110", "title": "Exception State"}, {"address": 506, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", "function": "divisionby0(uint256)", "max_gas_used": 367, "min_gas_used": 272, "severity": "Low", "sourceMap": null, "swc-id": "110", "title": "Exception State"}, {"address": 531, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", "function": "assert1()", "max_gas_used": 363, "min_gas_used": 268, "severity": "Low", "sourceMap": null, "swc-id": "110", "title": "Exception State"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 446, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", |
||||
"function": "assert3(uint256)", |
||||
"max_gas_used": 301, |
||||
"min_gas_used": 206, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "110", |
||||
"title": "Exception State" |
||||
}, |
||||
{ |
||||
"address": 484, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", |
||||
"function": "arrayaccess(uint256)", |
||||
"max_gas_used": 351, |
||||
"min_gas_used": 256, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "110", |
||||
"title": "Exception State" |
||||
}, |
||||
{ |
||||
"address": 506, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", |
||||
"function": "divisionby0(uint256)", |
||||
"max_gas_used": 367, |
||||
"min_gas_used": 272, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "110", |
||||
"title": "Exception State" |
||||
}, |
||||
{ |
||||
"address": 531, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A reachable exception has been detected.\nIt is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.", |
||||
"function": "assert1()", |
||||
"max_gas_used": 363, |
||||
"min_gas_used": 268, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "110", |
||||
"title": "Exception State" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,72 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "A reachable exception has been detected.", |
||||
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "446:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-110", |
||||
"swcTitle": "Assert Violation" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "A reachable exception has been detected.", |
||||
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "484:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-110", |
||||
"swcTitle": "Assert Violation" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "A reachable exception has been detected.", |
||||
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "506:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-110", |
||||
"swcTitle": "Assert Violation" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "A reachable exception has been detected.", |
||||
"tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "531:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-110", |
||||
"swcTitle": "Assert Violation" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0x4a773a86bc6fb269f88bf09bb3094de29b6073cf13b1760e9d01d957f50a9dfd" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "446:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "484:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "506:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}, {"description": {"head": "A reachable exception has been detected.", "tail": "It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking."}, "extra": {}, "locations": [{"sourceMap": "531:1:0"}], "severity": "Low", "swcID": "SWC-110", "swcTitle": "Assert Violation"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x4a773a86bc6fb269f88bf09bb3094de29b6073cf13b1760e9d01d957f50a9dfd"], "sourceType": "raw-bytecode"}] |
@ -1 +1,71 @@ |
||||
{"error": null, "issues": [{"address": 618, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "_function_0x141f32ff", "max_gas_used": 35865, "min_gas_used": 1113, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}, {"address": 618, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Use of callcode is deprecated.\nThe callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead.", "function": "_function_0x141f32ff", "max_gas_used": 1141, "min_gas_used": 389, "severity": "Medium", "sourceMap": null, "swc-id": "111", "title": "Use of callcode"}, {"address": 849, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "_function_0x9b58bc26", "max_gas_used": 35922, "min_gas_used": 1170, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on thecontract state.", "function": "_function_0xeea4c864", "max_gas_used": 1223, "min_gas_used": 471, "severity": "Medium", "sourceMap": null, "swc-id": "107", "title": "External Call To User-Supplied Address"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "_function_0xeea4c864", "max_gas_used": 35947, "min_gas_used": 1195, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 618, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "_function_0x141f32ff", |
||||
"max_gas_used": 35865, |
||||
"min_gas_used": 1113, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"address": 618, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Use of callcode is deprecated.\nThe callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead.", |
||||
"function": "_function_0x141f32ff", |
||||
"max_gas_used": 1141, |
||||
"min_gas_used": 389, |
||||
"severity": "Medium", |
||||
"sourceMap": null, |
||||
"swc-id": "111", |
||||
"title": "Use of callcode" |
||||
}, |
||||
{ |
||||
"address": 849, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "_function_0x9b58bc26", |
||||
"max_gas_used": 35928, |
||||
"min_gas_used": 1176, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"address": 1038, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "A call to a user-supplied address is executed.\nThe callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state.", |
||||
"function": "_function_0xeea4c864", |
||||
"max_gas_used": 1229, |
||||
"min_gas_used": 477, |
||||
"severity": "Medium", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To User-Supplied Address" |
||||
}, |
||||
{ |
||||
"address": 1038, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "_function_0xeea4c864", |
||||
"max_gas_used": 35953, |
||||
"min_gas_used": 1201, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,87 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "Use of callcode is deprecated.", |
||||
"tail": "The callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "618:1:0" |
||||
} |
||||
], |
||||
"severity": "Medium", |
||||
"swcID": "SWC-111", |
||||
"swcTitle": "Use of Deprecated Solidity Functions" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "A call to a user-supplied address is executed.", |
||||
"tail": "The callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on thecontract state." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "1038:1:0" |
||||
} |
||||
], |
||||
"severity": "Medium", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "618:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "849:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "1038:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0x6daec61d05d8f1210661e7e7d1ed6d72bd6ade639398fac1e867aff50abfc1c1" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "Use of callcode is deprecated.", "tail": "The callcode method executes code of another contract in the context of the caller account. Due to a bug in the implementation it does not persist sender and value over the call. It was therefore deprecated and may be removed in the future. Use the delegatecall method instead."}, "extra": {}, "locations": [{"sourceMap": "618:1:0"}], "severity": "Medium", "swcID": "SWC-111", "swcTitle": "Use of Deprecated Solidity Functions"}, {"description": {"head": "A call to a user-supplied address is executed.", "tail": "The callee address of an external message call can be set by the caller. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent averse effects on the contract state."}, "extra": {}, "locations": [{"sourceMap": "1038:1:0"}], "severity": "Medium", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "618:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "849:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "1038:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x6daec61d05d8f1210661e7e7d1ed6d72bd6ade639398fac1e867aff50abfc1c1"], "sourceType": "raw-bytecode"}] |
@ -1 +1,5 @@ |
||||
{"error": null, "issues": [], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [], |
||||
"success": true |
||||
} |
@ -1,9 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": [], "sourceType": "raw-bytecode"}] |
@ -1 +1,19 @@ |
||||
{"error": null, "issues": [{"address": 142, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Anyone can withdraw ETH from the contract account.\nArbitrary 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": "transfer()", "max_gas_used": 467, "min_gas_used": 186, "severity": "High", "sourceMap": null, "swc-id": "105", "title": "Unprotected Ether Withdrawal"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 142, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Anyone can withdraw ETH from the contract account.\nArbitrary 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": "transfer()", |
||||
"max_gas_used": 467, |
||||
"min_gas_used": 186, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "105", |
||||
"title": "Unprotected Ether Withdrawal" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,27 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "Anyone can withdraw ETH from the contract account.", |
||||
"tail": "Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "142:1:0" |
||||
} |
||||
], |
||||
"severity": "High", |
||||
"swcID": "SWC-105", |
||||
"swcTitle": "Unprotected Ether Withdrawal" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0xbc9c3d9db56d20cf4ca3b6fd88ff9215cf728a092cca1ed8edb83272b933ff5b" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "Anyone can withdraw ETH from the contract account.", "tail": "Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability."}, "extra": {}, "locations": [{"sourceMap": "142:1:0"}], "severity": "High", "swcID": "SWC-105", "swcTitle": "Unprotected Ether Withdrawal"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xbc9c3d9db56d20cf4ca3b6fd88ff9215cf728a092cca1ed8edb83272b933ff5b"], "sourceType": "raw-bytecode"}] |
@ -1 +1,5 @@ |
||||
{"error": null, "issues": [], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [], |
||||
"success": true |
||||
} |
@ -1,9 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": [], "sourceType": "raw-bytecode"}] |
@ -1 +1,19 @@ |
||||
{"error": null, "issues": [{"address": 317, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "Use of tx.origin is deprecated.\nThe smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", "function": "transferOwnership(address)", "max_gas_used": 1051, "min_gas_used": 626, "severity": "Medium", "sourceMap": null, "swc-id": "111", "title": "Use of tx.origin"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 317, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Use of tx.origin is deprecated.\nThe smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", |
||||
"function": "transferOwnership(address)", |
||||
"max_gas_used": 1051, |
||||
"min_gas_used": 626, |
||||
"severity": "Medium", |
||||
"sourceMap": null, |
||||
"swc-id": "111", |
||||
"title": "Use of tx.origin" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,27 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "Use of tx.origin is deprecated.", |
||||
"tail": "The smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin" |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "317:1:0" |
||||
} |
||||
], |
||||
"severity": "Medium", |
||||
"swcID": "SWC-111", |
||||
"swcTitle": "Use of Deprecated Solidity Functions" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0x25b20ef097dfc0aa56a932c4e09f06ee02a69c005767df86877f48c6c2412f03" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "Use of tx.origin is deprecated.", "tail": "The smart contract retrieves the transaction origin (tx.origin) using msg.origin. Use of msg.origin is deprecated and the instruction may be removed in the future. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin"}, "extra": {}, "locations": [{"sourceMap": "317:1:0"}], "severity": "Medium", "swcID": "SWC-111", "swcTitle": "Use of Deprecated Solidity Functions"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x25b20ef097dfc0aa56a932c4e09f06ee02a69c005767df86877f48c6c2412f03"], "sourceType": "raw-bytecode"}] |
@ -1,29 +1,32 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [{ |
||||
"issues": [ |
||||
{ |
||||
"address": 567, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The binary subtraction can underflow.\nThe operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.", |
||||
"function": "sendeth(address,uint256)", |
||||
"max_gas_used": 1053, |
||||
"min_gas_used": 768, |
||||
"max_gas_used": 78155, |
||||
"min_gas_used": 17019, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow" |
||||
}, { |
||||
}, |
||||
{ |
||||
"address": 649, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The binary subtraction can underflow.\nThe operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.", |
||||
"function": "sendeth(address,uint256)", |
||||
"max_gas_used": 1774, |
||||
"min_gas_used": 1299, |
||||
"max_gas_used": 78155, |
||||
"min_gas_used": 17019, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow" |
||||
}], |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,42 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "The binary subtraction can underflow.", |
||||
"tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "567:1:0" |
||||
} |
||||
], |
||||
"severity": "High", |
||||
"swcID": "SWC-101", |
||||
"swcTitle": "Integer Overflow and Underflow" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The binary subtraction can underflow.", |
||||
"tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "649:1:0" |
||||
} |
||||
], |
||||
"severity": "High", |
||||
"swcID": "SWC-101", |
||||
"swcTitle": "Integer Overflow and Underflow" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0xf230bec502569e8b7e7737616d0ad0f200c436624e3c223e5398c0615cd2d6b9" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "The binary subtraction can underflow.", "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."}, "extra": {}, "locations": [{"sourceMap": "567:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}, {"description": {"head": "The binary subtraction can underflow.", "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."}, "extra": {}, "locations": [{"sourceMap": "649:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xf230bec502569e8b7e7737616d0ad0f200c436624e3c223e5398c0615cd2d6b9"], "sourceType": "raw-bytecode"}] |
@ -1 +1,45 @@ |
||||
{"error": null, "issues": [{"address": 196, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "function": "callchecked()", "max_gas_used": 1210, "min_gas_used": 599, "severity": "Low", "sourceMap": null, "swc-id": "107", "title": "External Call To Fixed Address"}, {"address": 285, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", "function": "callnotchecked()", "max_gas_used": 1232, "min_gas_used": 621, "severity": "Low", "sourceMap": null, "swc-id": "107", "title": "External Call To Fixed Address"}, {"address": 285, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", "function": "callnotchecked()", "max_gas_used": 35950, "min_gas_used": 1339, "severity": "Low", "sourceMap": null, "swc-id": "104", "title": "Unchecked Call Return Value"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 196, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", |
||||
"function": "callchecked()", |
||||
"max_gas_used": 1210, |
||||
"min_gas_used": 599, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To Fixed Address" |
||||
}, |
||||
{ |
||||
"address": 285, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes an external message call.\nAn external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully.", |
||||
"function": "callnotchecked()", |
||||
"max_gas_used": 1232, |
||||
"min_gas_used": 621, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "107", |
||||
"title": "External Call To Fixed Address" |
||||
}, |
||||
{ |
||||
"address": 285, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of a message call is not checked.\nExternal calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states.", |
||||
"function": "callnotchecked()", |
||||
"max_gas_used": 35950, |
||||
"min_gas_used": 1339, |
||||
"severity": "Low", |
||||
"sourceMap": null, |
||||
"swc-id": "104", |
||||
"title": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,57 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "The contract executes an external message call.", |
||||
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "196:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The contract executes an external message call.", |
||||
"tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "285:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-107", |
||||
"swcTitle": "Reentrancy" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The return value of a message call is not checked.", |
||||
"tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "285:1:0" |
||||
} |
||||
], |
||||
"severity": "Low", |
||||
"swcID": "SWC-104", |
||||
"swcTitle": "Unchecked Call Return Value" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0xb191cf6cc0d8cc37a91c9d88019cc011b932169fb5776df616e2bb9cd93b4039" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "196:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The contract executes an external message call.", "tail": "An external function call to a fixed contract address is executed. Make sure that the callee contract has been reviewed carefully."}, "extra": {}, "locations": [{"sourceMap": "285:1:0"}], "severity": "Low", "swcID": "SWC-107", "swcTitle": "Reentrancy"}, {"description": {"head": "The return value of a message call is not checked.", "tail": "External calls return a boolean value. If the callee contract halts with an exception, 'false' is returned and execution continues in the caller. It is usually recommended to wrap external calls into a require statement to prevent unexpected states."}, "extra": {}, "locations": [{"sourceMap": "285:1:0"}], "severity": "Low", "swcID": "SWC-104", "swcTitle": "Unchecked Call Return Value"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xb191cf6cc0d8cc37a91c9d88019cc011b932169fb5776df616e2bb9cd93b4039"], "sourceType": "raw-bytecode"}] |
@ -1,19 +1,19 @@ |
||||
{ |
||||
"error" : null, |
||||
"issues" : [ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"title" : "Unprotected Selfdestruct", |
||||
"swc-id" : "106", |
||||
"severity" : "High", |
||||
"contract" : "Unknown", |
||||
"description" : "The contract can be killed by anyone.\nAnyone can kill this contract and withdraw its balance to an arbitrary address.", |
||||
"function" : "kill(address)", |
||||
"min_gas_used" : 168, |
||||
"max_gas_used" : 263, |
||||
"debug" : "<DEBUG-DATA>", |
||||
"sourceMap" : null, |
||||
"address" : 146 |
||||
"address": 146, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract can be killed by anyone.\nAnyone can kill this contract and withdraw its balance to an arbitrary address.", |
||||
"function": "kill(address)", |
||||
"max_gas_used": 263, |
||||
"min_gas_used": 168, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "106", |
||||
"title": "Unprotected Selfdestruct" |
||||
} |
||||
], |
||||
"success" : true |
||||
"success": true |
||||
} |
@ -1,27 +1 @@ |
||||
[ |
||||
{ |
||||
"issues" : [ |
||||
{ |
||||
"swcTitle" : "Unprotected SELFDESTRUCT Instruction", |
||||
"locations" : [ |
||||
{ |
||||
"sourceMap" : "146:1:0" |
||||
} |
||||
], |
||||
"extra" : {}, |
||||
"description" : { |
||||
"tail" : "Anyone can kill this contract and withdraw its balance to an arbitrary address.", |
||||
"head" : "The contract can be killed by anyone." |
||||
}, |
||||
"severity" : "High", |
||||
"swcID" : "SWC-106" |
||||
} |
||||
], |
||||
"sourceFormat" : "evm-byzantium-bytecode", |
||||
"meta" : {}, |
||||
"sourceType" : "raw-bytecode", |
||||
"sourceList" : [ |
||||
"0x2fb801366b61a05b30550481a1c8f7d5f20de0b93d9f2f2ce2b28c4e322033c9" |
||||
] |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "The contract can be killed by anyone.", "tail": "Anyone can kill this contract and withdraw its balance to an arbitrary address."}, "extra": {}, "locations": [{"sourceMap": "146:1:0"}], "severity": "High", "swcID": "SWC-106", "swcTitle": "Unprotected SELFDESTRUCT Instruction"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0x2fb801366b61a05b30550481a1c8f7d5f20de0b93d9f2f2ce2b28c4e322033c9"], "sourceType": "raw-bytecode"}] |
@ -1,29 +1,32 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [{ |
||||
"issues": [ |
||||
{ |
||||
"address": 567, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The binary subtraction can underflow.\nThe operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.", |
||||
"function": "sendeth(address,uint256)", |
||||
"max_gas_used": 1053, |
||||
"min_gas_used": 768, |
||||
"max_gas_used": 52861, |
||||
"min_gas_used": 11915, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow" |
||||
}, { |
||||
}, |
||||
{ |
||||
"address": 649, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The binary subtraction can underflow.\nThe operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion.", |
||||
"function": "sendeth(address,uint256)", |
||||
"max_gas_used": 1774, |
||||
"min_gas_used": 1299, |
||||
"max_gas_used": 52861, |
||||
"min_gas_used": 11915, |
||||
"severity": "High", |
||||
"sourceMap": null, |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow" |
||||
}], |
||||
} |
||||
], |
||||
"success": true |
||||
} |
@ -1,42 +1 @@ |
||||
[ |
||||
{ |
||||
"issues": [ |
||||
{ |
||||
"description": { |
||||
"head": "The binary subtraction can underflow.", |
||||
"tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "567:1:0" |
||||
} |
||||
], |
||||
"severity": "High", |
||||
"swcID": "SWC-101", |
||||
"swcTitle": "Integer Overflow and Underflow" |
||||
}, |
||||
{ |
||||
"description": { |
||||
"head": "The binary subtraction can underflow.", |
||||
"tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion." |
||||
}, |
||||
"extra": {}, |
||||
"locations": [ |
||||
{ |
||||
"sourceMap": "649:1:0" |
||||
} |
||||
], |
||||
"severity": "High", |
||||
"swcID": "SWC-101", |
||||
"swcTitle": "Integer Overflow and Underflow" |
||||
} |
||||
], |
||||
"meta": {}, |
||||
"sourceFormat": "evm-byzantium-bytecode", |
||||
"sourceList": [ |
||||
"0xabef56740bf7795a9f8732e4781ebd27f2977f8a4997e3ff11cee79a4ba6c0ce" |
||||
], |
||||
"sourceType": "raw-bytecode" |
||||
} |
||||
] |
||||
[{"issues": [{"description": {"head": "The binary subtraction can underflow.", "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."}, "extra": {}, "locations": [{"sourceMap": "567:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}, {"description": {"head": "The binary subtraction can underflow.", "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."}, "extra": {}, "locations": [{"sourceMap": "649:1:0"}], "severity": "High", "swcID": "SWC-101", "swcTitle": "Integer Overflow and Underflow"}], "meta": {}, "sourceFormat": "evm-byzantium-bytecode", "sourceList": ["0xabef56740bf7795a9f8732e4781ebd27f2977f8a4997e3ff11cee79a4ba6c0ce"], "sourceType": "raw-bytecode"}] |
Loading…
Reference in new issue