mirror of https://github.com/ConsenSys/mythril
parent
f1a0c9db04
commit
07347e28ff
@ -1,205 +0,0 @@ |
||||
"""This module contains functionality used to easily analyse Truffle |
||||
projects.""" |
||||
import json |
||||
import logging |
||||
import os |
||||
import re |
||||
import sys |
||||
import warnings |
||||
from pathlib import PurePath |
||||
|
||||
from ethereum.utils import sha3 |
||||
|
||||
from mythril.analysis.report import Report |
||||
from mythril.analysis.security import fire_lasers |
||||
from mythril.analysis.symbolic import SymExecWrapper |
||||
from mythril.ethereum import util |
||||
from mythril.ethereum.evmcontract import EVMContract |
||||
from mythril.laser.ethereum.util import get_instruction_index |
||||
from mythril.solidity.soliditycontract import SourceMapping |
||||
|
||||
log = logging.getLogger(__name__) |
||||
|
||||
|
||||
def format_Warning(message, category, filename, lineno, line=""): |
||||
return "{}: {}\n\n".format(str(filename), str(message)) |
||||
|
||||
|
||||
warnings.formatwarning = format_Warning |
||||
|
||||
|
||||
def analyze_truffle_project(sigs, args): |
||||
""" |
||||
|
||||
:param sigs: |
||||
:param args: |
||||
""" |
||||
warnings.warn( |
||||
"The option --truffle is being deprecated, Please use the truffle-security plugin, https://github.com/ConsenSys/truffle-security", |
||||
FutureWarning, |
||||
) |
||||
|
||||
project_root = os.getcwd() |
||||
|
||||
build_dir = os.path.join(project_root, "build", "contracts") |
||||
|
||||
files = os.listdir(build_dir) |
||||
|
||||
for filename in files: |
||||
|
||||
if re.match(r".*\.json$", filename) and filename != "Migrations.json": |
||||
|
||||
with open(os.path.join(build_dir, filename)) as cf: |
||||
contractdata = json.load(cf) |
||||
|
||||
try: |
||||
name = contractdata["contractName"] |
||||
bytecode = contractdata["deployedBytecode"] |
||||
filename = PurePath(contractdata["sourcePath"]).name |
||||
except KeyError: |
||||
print( |
||||
"Unable to parse contract data. Please use Truffle 4 to compile your project." |
||||
) |
||||
sys.exit() |
||||
if len(bytecode) < 4: |
||||
continue |
||||
get_sigs_from_truffle(sigs, contractdata) |
||||
|
||||
ethcontract = EVMContract(bytecode, name=name) |
||||
|
||||
address = util.get_indexed_address(0) |
||||
sym = SymExecWrapper( |
||||
ethcontract, |
||||
address, |
||||
args.strategy, |
||||
max_depth=args.max_depth, |
||||
create_timeout=args.create_timeout, |
||||
execution_timeout=args.execution_timeout, |
||||
transaction_count=args.transaction_count, |
||||
modules=args.modules or [], |
||||
compulsory_statespace=False, |
||||
) |
||||
issues = fire_lasers(sym) |
||||
|
||||
if not len(issues): |
||||
if args.outform == "text" or args.outform == "markdown": |
||||
print("# Analysis result for " + name + "\n\nNo issues found.") |
||||
else: |
||||
result = { |
||||
"contract": name, |
||||
"result": {"success": True, "error": None, "issues": []}, |
||||
} |
||||
print(json.dumps(result)) |
||||
else: |
||||
|
||||
report = Report() |
||||
# augment with source code |
||||
|
||||
deployed_disassembly = ethcontract.disassembly |
||||
constructor_disassembly = ethcontract.creation_disassembly |
||||
|
||||
source = contractdata["source"] |
||||
|
||||
deployed_source_map = contractdata["deployedSourceMap"].split(";") |
||||
source_map = contractdata["sourceMap"].split(";") |
||||
|
||||
deployed_mappings = get_mappings(source, deployed_source_map) |
||||
constructor_mappings = get_mappings(source, source_map) |
||||
|
||||
for issue in issues: |
||||
if issue.function == "constructor": |
||||
mappings = constructor_mappings |
||||
disassembly = constructor_disassembly |
||||
else: |
||||
mappings = deployed_mappings |
||||
disassembly = deployed_disassembly |
||||
|
||||
index = get_instruction_index( |
||||
disassembly.instruction_list, issue.address |
||||
) |
||||
|
||||
if index: |
||||
try: |
||||
offset = mappings[index].offset |
||||
length = mappings[index].length |
||||
|
||||
issue.filename = filename |
||||
issue.code = source.encode("utf-8")[ |
||||
offset : offset + length |
||||
].decode("utf-8") |
||||
issue.lineno = mappings[index].lineno |
||||
except IndexError: |
||||
log.debug("No code mapping at index %d", index) |
||||
|
||||
report.append_issue(issue) |
||||
|
||||
if args.outform == "json": |
||||
|
||||
result = { |
||||
"contract": name, |
||||
"result": { |
||||
"success": True, |
||||
"error": None, |
||||
"issues": list(map(lambda x: x.as_dict, issues)), |
||||
}, |
||||
} |
||||
print(json.dumps(result)) |
||||
|
||||
else: |
||||
if args.outform == "text": |
||||
print( |
||||
"# Analysis result for " + name + ":\n\n" + report.as_text() |
||||
) |
||||
elif args.outform == "markdown": |
||||
print(report.as_markdown()) |
||||
|
||||
|
||||
def get_sigs_from_truffle(sigs, contract_data): |
||||
""" |
||||
|
||||
:param sigs: |
||||
:param contract_data: |
||||
""" |
||||
abis = contract_data["abi"] |
||||
for abi in abis: |
||||
if abi["type"] != "function": |
||||
continue |
||||
function_name = abi["name"] |
||||
list_of_args = ",".join([input["type"] for input in abi["inputs"]]) |
||||
signature = function_name + "(" + list_of_args + ")" |
||||
sigs.add("0x" + sha3(signature)[:4].hex(), signature) |
||||
|
||||
|
||||
def get_mappings(source, deployed_source_map): |
||||
""" |
||||
|
||||
:param source: |
||||
:param deployed_source_map: |
||||
:return: |
||||
""" |
||||
mappings = [] |
||||
prev_item = "" |
||||
for item in deployed_source_map: |
||||
if item == "": |
||||
item = prev_item |
||||
|
||||
mapping = item.split(":") |
||||
|
||||
if len(mapping) > 0 and len(mapping[0]) > 0: |
||||
offset = int(mapping[0]) |
||||
|
||||
if len(mapping) > 1 and len(mapping[1]) > 0: |
||||
length = int(mapping[1]) |
||||
|
||||
if len(mapping) > 2 and len(mapping[2]) > 0: |
||||
idx = int(mapping[2]) |
||||
|
||||
if idx == -1: |
||||
lineno = None |
||||
else: |
||||
lineno = source.encode("utf-8")[0:offset].count("\n".encode("utf-8")) + 1 |
||||
prev_item = item |
||||
|
||||
mappings.append(SourceMapping(idx, offset, length, lineno, item)) |
||||
|
||||
return mappings |
@ -1,30 +0,0 @@ |
||||
Truffle Hello World Demo |
||||
======================== |
||||
|
||||
``` |
||||
npm install -g truffle ethereumjs-testrpc |
||||
``` |
||||
|
||||
This repo is created by following commands: |
||||
|
||||
``` |
||||
truffle init |
||||
truffle compile |
||||
``` |
||||
|
||||
In order to run `truffle migrate`, we need to setup `truffle.js` first: |
||||
|
||||
``` |
||||
networks: { |
||||
development: { |
||||
host: "localhost", |
||||
port: 8545, |
||||
network_id: "*" // Match any network id |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Resources |
||||
--------- |
||||
|
||||
- <https://medium.com/etherereum-salon/eth-testing-472c2f73b4c3> |
@ -1,23 +0,0 @@ |
||||
pragma solidity ^0.4.17; |
||||
|
||||
contract Migrations { |
||||
address public owner; |
||||
uint public last_completed_migration; |
||||
|
||||
modifier restricted() { |
||||
if (msg.sender == owner) _; |
||||
} |
||||
|
||||
function Migrations() public { |
||||
owner = msg.sender; |
||||
} |
||||
|
||||
function setCompleted(uint completed) public restricted { |
||||
last_completed_migration = completed; |
||||
} |
||||
|
||||
function upgrade(address new_address) public restricted { |
||||
Migrations upgraded = Migrations(new_address); |
||||
upgraded.setCompleted(last_completed_migration); |
||||
} |
||||
} |
@ -1,34 +0,0 @@ |
||||
contract Crowdfunding { |
||||
|
||||
mapping(address => uint) public balances; |
||||
address public owner; |
||||
uint256 INVEST_MIN = 1 ether; |
||||
uint256 INVEST_MAX = 10 ether; |
||||
|
||||
modifier onlyOwner() { |
||||
require(msg.sender == owner); |
||||
_; |
||||
} |
||||
|
||||
function crowdfunding() { |
||||
owner = msg.sender; |
||||
} |
||||
|
||||
function withdrawfunds() onlyOwner { |
||||
msg.sender.transfer(this.balance); |
||||
} |
||||
|
||||
function invest() public payable { |
||||
require(msg.value > INVEST_MIN && msg.value < INVEST_MAX); |
||||
|
||||
balances[msg.sender] += msg.value; |
||||
} |
||||
|
||||
function getBalance() public constant returns (uint) { |
||||
return balances[msg.sender]; |
||||
} |
||||
|
||||
function() public payable { |
||||
invest(); |
||||
} |
||||
} |
@ -1,5 +0,0 @@ |
||||
var Migrations = artifacts.require("./Migrations.sol"); |
||||
|
||||
module.exports = function(deployer) { |
||||
deployer.deploy(Migrations); |
||||
}; |
@ -1,4 +0,0 @@ |
||||
module.exports = { |
||||
// See <http://truffleframework.com/docs/advanced/configuration>
|
||||
// to customize your Truffle configuration!
|
||||
}; |
@ -1,11 +0,0 @@ |
||||
module.exports = { |
||||
// See <http://truffleframework.com/docs/advanced/configuration>
|
||||
// to customize your Truffle configuration!
|
||||
networks: { |
||||
development: { |
||||
host: "localhost", |
||||
port: 8545, |
||||
network_id: "*" // Match any network id
|
||||
} |
||||
} |
||||
}; |
Loading…
Reference in new issue