Merge branch 'develop' into modules_usability

pull/1340/head
Bernhard Mueller 5 years ago committed by GitHub
commit 0da22a957c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .circleci/config.yml
  2. 24
      docs/source/security-analysis.rst
  3. 13
      mythril/ethereum/interface/rpc/client.py
  4. 6
      mythril/interfaces/cli.py
  5. 29
      mythril/mythril/mythril_config.py
  6. 17
      tests/mythril/mythril_config_test.py
  7. 4
      tox.ini

@ -54,9 +54,9 @@ jobs:
working_directory: /home/mythril
no_output_timeout: 10m
environment:
LC_ALL: en_US.ASCII
LANG: en_US.ASCII
MYTHRIL_DIR: '/home/mythril'
INFURA_ID: $INFURA_ID
- store_test_results:
path: /home/mythril/.tox/output

@ -57,15 +57,15 @@ 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) |
+--------------------------------+-------------------------------------------------+
+-------------------------------------------------+-------------------------------------------------+
| :code:`--rpc ganache` | Connect to local Ganache |
+-------------------------------------------------+-------------------------------------------------+
| :code:`--rpc infura-[netname] --infura-id <ID>` | 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>`
@ -73,13 +73,14 @@ Analyze mainnet contract via INFURA:
.. code-block:: bash
myth analyze -a 0x5c436ff914c458983414019195e0f4ecbef9e6dd
myth analyze -a 0x5c436ff914c458983414019195e0f4ecbef9e6dd --infura-id <ID>
You can also use the environment variable `INFURA_ID` instead of the cmd line argument or set it in ~/.mythril/config.ini.
Adding the :code:`-l` flag will cause mythril to automatically retrieve dependencies, such as dynamically linked library contracts:
.. code-block:: bash
myth -v4 analyze -l -a 0xEbFD99838cb0c132016B9E117563CB41f2B02264
myth -v4 analyze -l -a 0xEbFD99838cb0c132016B9E117563CB41f2B02264 --infura-id <ID>
******************
Speed vs. Coverage
@ -88,3 +89,4 @@ 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.
-

@ -52,11 +52,20 @@ class EthJsonRpc(BaseClient):
:return:
"""
params = params or []
data = {"jsonrpc": "2.0", "method": method, "params": params, "id": _id}
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": _id,
}
scheme = "http"
if self.tls:
scheme += "s"
url = "{}://{}:{}".format(scheme, self.host, self.port)
if self.host:
url = "{}://{}:{}".format(scheme, self.host, self.port)
else:
url = "{}".format(scheme)
headers = {"Content-Type": JSON_MEDIA_TYPE}
log.debug("rpc send: %s" % json.dumps(data))
try:

@ -387,6 +387,10 @@ def create_analyzer_parser(analyzer_parser: ArgumentParser):
action="store_true",
help="analyze a truffle project (run from project dir)",
)
commands.add_argument(
"--infura-id", help="set infura id for onchain analysis",
)
options = analyzer_parser.add_argument_group("options")
options.add_argument(
"-m",
@ -542,6 +546,8 @@ def set_config(args: Namespace):
:return: modified config
"""
config = MythrilConfig()
if args.__dict__.get("infura_id", None):
config.set_api_infura_id(args.infura_id)
if (
args.command in ANALYZE_LIST
and (args.dynld or not args.no_onchain_storage_access)

@ -23,6 +23,7 @@ class MythrilConfig:
"""
def __init__(self):
self.infura_id = os.getenv("INFURA_ID") # type: str
self.mythril_dir = self._init_mythril_dir()
self.config_path = os.path.join(self.mythril_dir, "config.ini")
self.leveldb_dir = None
@ -30,6 +31,9 @@ class MythrilConfig:
self.eth = None # type: Optional[EthJsonRpc]
self.eth_db = None # type: Optional[EthLevelDB]
def set_api_infura_id(self, id):
self.infura_id = id
@staticmethod
def _init_mythril_dir() -> str:
"""
@ -83,12 +87,17 @@ class MythrilConfig:
if not config.has_option("defaults", "dynamic_loading"):
self._add_dynamic_loading_option(config)
if not config.has_option("defaults", "infura_id"):
config.set("defaults", "infura_id", "")
with codecs.open(self.config_path, "w", "utf-8") as fp:
config.write(fp)
leveldb_dir = config.get(
"defaults", "leveldb_dir", fallback=leveldb_default_path
)
if not self.infura_id:
self.infura_id = config.get("defaults", "infura_id", fallback="")
self.leveldb_dir = os.path.expanduser(leveldb_dir)
@staticmethod
@ -167,7 +176,9 @@ class MythrilConfig:
def set_api_rpc_infura(self) -> None:
"""Set the RPC mode to INFURA on Mainnet."""
log.info("Using INFURA Main Net for RPC queries")
self.eth = EthJsonRpc("mainnet.infura.io", 443, True)
self.eth = EthJsonRpc(
"mainnet.infura.io/v3/{}".format(self.infura_id), None, True
)
def set_api_rpc(self, rpc: str = None, rpctls: bool = False) -> None:
"""
@ -178,8 +189,20 @@ class MythrilConfig:
rpcconfig = ("localhost", 7545, 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)
if self.infura_id in (None, ""):
raise CriticalError(
"Infura key not provided. Use --infura-id <INFURA_ID> "
"or set it in the environment variable INFURA_ID "
"or in the ~/.mythril/config.ini file'"
)
rpcconfig = (
"{}.infura.io/v3/{}".format(m.group(1), self.infura_id),
None,
True,
)
else:
try:
host, port = rpc.split(":")
@ -191,7 +214,7 @@ class MythrilConfig:
if rpcconfig:
log.info("Using RPC settings: %s" % str(rpcconfig))
self.eth = EthJsonRpc(rpcconfig[0], int(rpcconfig[1]), rpcconfig[2])
self.eth = EthJsonRpc(rpcconfig[0], rpcconfig[1], rpcconfig[2])
else:
raise CriticalError("Invalid RPC settings, check help for details.")

@ -1,4 +1,5 @@
import pytest
import os
from configparser import ConfigParser
from pathlib import Path
@ -13,16 +14,15 @@ def test_config_path_dynloading():
Path(__file__).parent.parent / "testdata/mythril_config_inputs/config.ini"
)
config.set_api_from_config_path()
assert config.eth.host == "mainnet.infura.io"
assert config.eth.port == 443
assert "mainnet.infura.io/v3/" in config.eth.host
rpc_types_tests = [
("infura", "mainnet.infura.io", 443, True),
("ganache", "localhost", 7545, True),
("infura-rinkeby", "rinkeby.infura.io", 443, True),
("infura-ropsten", "ropsten.infura.io", 443, True),
("infura-kovan", "kovan.infura.io", 443, True),
("infura", "mainnet.infura.io/v3/", None, True),
("ganache", "localhost", None, True),
("infura-rinkeby", "rinkeby.infura.io/v3/", None, True),
("infura-ropsten", "ropsten.infura.io/v3/", None, True),
("infura-kovan", "kovan.infura.io/v3/", None, True),
("localhost", "localhost", 8545, True),
("localhost:9022", "localhost", 9022, True),
("pinfura", None, None, False),
@ -35,8 +35,7 @@ def test_set_rpc(rpc_type, host, port, success):
config = MythrilConfig()
if success:
config._set_rpc(rpc_type)
assert config.eth.host == host
assert config.eth.port == port
assert host in config.eth.host
else:
with pytest.raises(CriticalError):
config._set_rpc(rpc_type)

@ -5,7 +5,7 @@ envlist = py36
deps =
pytest
pytest-mock
passenv = MYTHRIL_DIR = {homedir}
passenv = MYTHRIL_DIR INFURA_ID
whitelist_externals = mkdir
commands =
mkdir -p {toxinidir}/tests/testdata/outputs_current/
@ -24,7 +24,7 @@ deps =
pytest
pytest-mock
pytest-cov
passenv = MYTHRIL_DIR = {homedir}
passenv = MYTHRIL_DIR INFURA_ID
whitelist_externals = mkdir
commands =
mypy --follow-imports=silent --warn-unused-ignores --ignore-missing-imports --no-strict-optional mythril

Loading…
Cancel
Save