Resolve merge conflicts

pull/366/head
Nikhil Parasaram 6 years ago
commit 7dc9b4b6d6
  1. 4
      .circleci/config.yml
  2. 2
      README.md
  3. 20
      mythril/analysis/modules/ether_send.py
  4. 3
      mythril/disassembler/disassembly.py
  5. 22
      mythril/ether/ethcontract.py
  6. 10
      mythril/ether/soliditycontract.py
  7. 13
      mythril/interfaces/cli.py
  8. 42
      mythril/laser/ethereum/instructions.py
  9. 6
      mythril/laser/ethereum/state.py
  10. 3
      mythril/laser/ethereum/svm.py
  11. 15
      mythril/laser/ethereum/taint_analysis.py
  12. 11
      mythril/leveldb/client.py
  13. 23
      mythril/mythril.py
  14. 3
      mythril/version.py
  15. 9
      setup.py
  16. 299
      solidity_examples/BECToken.sol
  17. 396
      solidity_examples/WalletLibrary.sol
  18. 31
      solidity_examples/ether_send.sol
  19. 21
      solidity_examples/etherstore.sol
  20. 12
      solidity_examples/hashforether.sol
  21. 21
      solidity_examples/timelock.sol
  22. 6
      solidity_examples/token.sol

@ -57,6 +57,10 @@ jobs:
command: python3 setup.py install command: python3 setup.py install
working_directory: /home/mythril working_directory: /home/mythril
- run:
name: Sonar analysis
command: if [ -z "$CIRCLE_PR_NUMBER" ]; then if [ -z "$CIRCLE_TAG" ]; then sonar-scanner -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.organization=$SONAR_ORGANIZATION -Dsonar.branch.name=$CIRCLE_BRANCH -Dsonar.projectBaseDir=/home/mythril -Dsonar.sources=mythril -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN; fi; fi
- run: - run:
name: Integration tests name: Integration tests
command: if [ -z "$CIRCLE_PR_NUMBER" ]; then ./run-integration-tests.sh; fi command: if [ -z "$CIRCLE_PR_NUMBER" ]; then ./run-integration-tests.sh; fi

@ -26,7 +26,7 @@ See the [Wiki](https://github.com/ConsenSys/mythril/wiki/Installation-and-Setup)
## Usage ## Usage
Documentation has moved to the [Wiki page](https://github.com/ConsenSys/mythril/wiki). Documentation has moved to the [Wiki page](https://github.com/ConsenSys/mythril/wiki). For support, visit the [Gitter channel](https://gitter.im/ConsenSys/mythril) or [Telegram group](https://t.me/mythril_tool).
## Publications and Videos ## Publications and Videos

@ -27,14 +27,13 @@ def execute(statespace):
state = call.state state = call.state
address = state.get_current_instruction()['address'] address = state.get_current_instruction()['address']
if ("callvalue" in str(call.value)): if "callvalue" in str(call.value):
logging.debug("[ETHER_SEND] Skipping refund function") logging.debug("[ETHER_SEND] Skipping refund function")
continue continue
# We're only interested in calls that send Ether # We're only interested in calls that send Ether
if call.value.type == VarType.CONCRETE: if call.value.type == VarType.CONCRETE and call.value.val == 0:
if call.value.val == 0:
continue continue
interesting = False interesting = False
@ -52,14 +51,14 @@ def execute(statespace):
else: else:
m = re.search(r'storage_([a-z0-9_&^]+)', str(call.to)) m = re.search(r'storage_([a-z0-9_&^]+)', str(call.to))
if (m): if m:
idx = m.group(1) idx = m.group(1)
description += "a non-zero amount of Ether is sent to an address taken from storage slot " + str(idx) + ".\n" description += "a non-zero amount of Ether is sent to an address taken from storage slot " + str(idx) + ".\n"
func = statespace.find_storage_write(state.environment.active_account.address, idx) func = statespace.find_storage_write(state.environment.active_account.address, idx)
if (func): if func:
description += "There is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`.\n" description += "There is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`.\n"
interesting = True interesting = True
else: else:
@ -74,7 +73,7 @@ def execute(statespace):
index = 0 index = 0
while(can_solve and index < len(node.constraints)): while can_solve and index < len(node.constraints):
constraint = node.constraints[index] constraint = node.constraints[index]
index += 1 index += 1
@ -82,14 +81,14 @@ def execute(statespace):
m = re.search(r'storage_([a-z0-9_&^]+)', str(constraint)) m = re.search(r'storage_([a-z0-9_&^]+)', str(constraint))
if (m): if m:
constrained = True constrained = True
idx = m.group(1) idx = m.group(1)
func = statespace.find_storage_write(state.environment.active_account.address, idx) func = statespace.find_storage_write(state.environment.active_account.address, idx)
if (func): if func:
description += "\nThere is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`." description += "\nThere is a check on storage index " + str(idx) + ". This storage slot can be written to by calling the function `" + func + "`."
else: else:
logging.debug("[ETHER_SEND] No storage writes to index " + str(idx)) logging.debug("[ETHER_SEND] No storage writes to index " + str(idx))
@ -98,7 +97,7 @@ def execute(statespace):
# CALLER may also be constrained to hardcoded address. I.e. 'caller' and some integer # CALLER may also be constrained to hardcoded address. I.e. 'caller' and some integer
elif (re.search(r"caller", str(constraint)) and re.search(r'[0-9]{20}', str(constraint))): elif re.search(r"caller", str(constraint)) and re.search(r'[0-9]{20}', str(constraint)):
constrained = True constrained = True
can_solve = False can_solve = False
break break
@ -116,7 +115,8 @@ def execute(statespace):
debug = "SOLVER OUTPUT:\n" + solver.pretty_print_model(model) debug = "SOLVER OUTPUT:\n" + solver.pretty_print_model(model)
issue = Issue(call.node.contract_name, call.node.function_name, address, "Ether send", "Warning", description, debug) issue = Issue(call.node.contract_name, call.node.function_name, address, "Ether send", "Warning",
description, debug)
issues.append(issue) issues.append(issue)
except UnsatError: except UnsatError:

@ -7,7 +7,7 @@ class Disassembly(object):
def __init__(self, code): def __init__(self, code):
self.instruction_list = asm.disassemble(util.safe_decode(code)) self.instruction_list = asm.disassemble(util.safe_decode(code))
self.xrefs = [] self.func_hashes = []
self.func_to_addr = {} self.func_to_addr = {}
self.addr_to_func = {} self.addr_to_func = {}
self.bytecode = code self.bytecode = code
@ -24,6 +24,7 @@ class Disassembly(object):
for i in jmptable_indices: for i in jmptable_indices:
func_hash = self.instruction_list[i]['argument'] func_hash = self.instruction_list[i]['argument']
self.func_hashes.append(func_hash)
try: try:
# tries local cache, file and optional online lookup # tries local cache, file and optional online lookup
# may return more than one function signature. since we cannot probe for the correct one we'll use the first # may return more than one function signature. since we cannot probe for the correct one we'll use the first

@ -31,12 +31,12 @@ class ETHContract(persistent.Persistent):
def get_easm(self): def get_easm(self):
return Disassembly(self.code).get_easm() return self.disassembly.get_easm()
def matches_expression(self, expression): def matches_expression(self, expression):
easm_code = self.get_easm()
str_eval = '' str_eval = ''
easm_code = None
matches = re.findall(r'func#([a-zA-Z0-9\s_,(\\)\[\]]+)#', expression) matches = re.findall(r'func#([a-zA-Z0-9\s_,(\\)\[\]]+)#', expression)
@ -58,6 +58,9 @@ class ETHContract(persistent.Persistent):
m = re.match(r'^code#([a-zA-Z0-9\s,\[\]]+)#', token) m = re.match(r'^code#([a-zA-Z0-9\s,\[\]]+)#', token)
if (m): if (m):
if easm_code is None:
easm_code = self.get_easm()
code = m.group(1).replace(",", "\\n") code = m.group(1).replace(",", "\\n")
str_eval += "\"" + code + "\" in easm_code" str_eval += "\"" + code + "\" in easm_code"
continue continue
@ -65,21 +68,8 @@ class ETHContract(persistent.Persistent):
m = re.match(r'^func#([a-fA-F0-9]+)#$', token) m = re.match(r'^func#([a-fA-F0-9]+)#$', token)
if (m): if (m):
str_eval += "\"" + m.group(1) + "\" in easm_code" str_eval += "\"" + m.group(1) + "\" in self.disassembly.func_hashes"
continue continue
return eval(str_eval.strip()) return eval(str_eval.strip())
class InstanceList(persistent.Persistent):
def __init__(self):
self.addresses = []
self.balances = []
pass
def add(self, address, balance=0):
self.addresses.append(address)
self.balances.append(balance)
self._p_changed = True

@ -27,6 +27,14 @@ class SourceCodeInfo:
self.code = code self.code = code
def get_contracts_from_file(input_file, solc_args=None):
data = get_solc_json(input_file, solc_args=solc_args)
for key, contract in data['contracts'].items():
filename, name = key.split(":")
if filename == input_file and len(contract['bin-runtime']):
yield SolidityContract(input_file, name, solc_args)
class SolidityContract(ETHContract): class SolidityContract(ETHContract):
def __init__(self, input_file, name=None, solc_args=None): def __init__(self, input_file, name=None, solc_args=None):
@ -48,7 +56,7 @@ class SolidityContract(ETHContract):
for key, contract in data['contracts'].items(): for key, contract in data['contracts'].items():
filename, _name = key.split(":") filename, _name = key.split(":")
if filename == input_file and name == _name: if filename == input_file and name == _name and len(contract['bin-runtime']):
name = name name = name
code = contract['bin-runtime'] code = contract['bin-runtime']
creation_code = contract['bin'] creation_code = contract['bin']

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: UTF-8 -*- # -*- coding: utf-8 -*-
"""mythril.py: Bug hunting on the Ethereum blockchain """mythril.py: Bug hunting on the Ethereum blockchain
http://www.github.com/ConsenSys/mythril http://www.github.com/ConsenSys/mythril
@ -14,6 +14,7 @@ import argparse
from mythril.exceptions import CriticalError from mythril.exceptions import CriticalError
from mythril.mythril import Mythril from mythril.mythril import Mythril
from mythril.version import VERSION
def exit_with_error(format, message): def exit_with_error(format, message):
@ -31,6 +32,8 @@ def main():
commands = parser.add_argument_group('commands') commands = parser.add_argument_group('commands')
commands.add_argument('-g', '--graph', help='generate a control flow graph') commands.add_argument('-g', '--graph', help='generate a control flow graph')
commands.add_argument('-V', '--version', action='store_true',
help='print the Mythril version number and exit')
commands.add_argument('-x', '--fire-lasers', action='store_true', commands.add_argument('-x', '--fire-lasers', action='store_true',
help='detect vulnerabilities, use with -c, -a or solidity file(s)') help='detect vulnerabilities, use with -c, -a or solidity file(s)')
commands.add_argument('-t', '--truffle', action='store_true', commands.add_argument('-t', '--truffle', action='store_true',
@ -85,6 +88,10 @@ def main():
args = parser.parse_args() args = parser.parse_args()
if args.version:
print("Mythril version {}".format(VERSION))
sys.exit()
# -- args sanity checks -- # -- args sanity checks --
# Detect unsupported combinations of command line args # Detect unsupported combinations of command line args
@ -191,7 +198,7 @@ def main():
exit_with_error(args.outform, "input files do not contain any valid contracts") exit_with_error(args.outform, "input files do not contain any valid contracts")
if args.graph: if args.graph:
html = mythril.graph_html(mythril.contracts[0], address=address, html = mythril.graph_html(strategy=args.strategy, contract=mythril.contracts[0], address=address,
enable_physics=args.enable_physics, phrackify=args.phrack, enable_physics=args.enable_physics, phrackify=args.phrack,
max_depth=args.max_depth) max_depth=args.max_depth)
@ -218,7 +225,7 @@ def main():
if not mythril.contracts: if not mythril.contracts:
exit_with_error(args.outform, "input files do not contain any valid contracts") exit_with_error(args.outform, "input files do not contain any valid contracts")
statespace = mythril.dump_statespace(mythril.contracts[0], address=address, max_depth=args.max_depth) statespace = mythril.dump_statespace(strategy=args.strategy, contract=mythril.contracts[0], address=address, max_depth=args.max_depth)
try: try:
with open(args.statespace_json, "w") as f: with open(args.statespace_json, "w") as f:

@ -515,7 +515,7 @@ class Instruction:
return [global_state] return [global_state]
@instruction @instruction
def codecopy(self, global_state): def codecopy_(self, global_state):
# FIXME: not implemented # FIXME: not implemented
state = global_state.mstate state = global_state.mstate
start, s1, size = state.stack.pop(), state.stack.pop(), state.stack.pop() start, s1, size = state.stack.pop(), state.stack.pop(), state.stack.pop()
@ -623,8 +623,10 @@ class Instruction:
@instruction @instruction
def mstore_(self, global_state): def mstore_(self, global_state):
state = global_state.mstate state = global_state.mstate
try:
op0, value = state.stack.pop(), state.stack.pop() op0, value = state.stack.pop(), state.stack.pop()
except IndexError:
raise StackUnderflowException()
try: try:
mstart = util.get_concrete_int(op0) mstart = util.get_concrete_int(op0)
@ -840,17 +842,16 @@ class Instruction:
except AttributeError: except AttributeError:
logging.debug("Return with symbolic length or offset. Not supported") logging.debug("Return with symbolic length or offset. Not supported")
#TODO: return 1
return_value = BitVec("retval_" + global_state.environment.active_function_name, 256) return_value = BitVec("retval_" + global_state.environment.active_function_name, 256)
state.stack.append(return_value)
if not global_state.call_stack: if not global_state.call_stack:
return [] return []
global_state.mstate.pc = global_state.call_stack.pop() new_global_state = deepcopy(global_state.call_stack.pop())
new_global_state.node = global_state.node
# TODO: copy memory
return [global_state] return [new_global_state]
@instruction @instruction
def suicide_(self, global_state): def suicide_(self, global_state):
@ -870,12 +871,11 @@ class Instruction:
@instruction @instruction
def stop_(self, global_state): def stop_(self, global_state):
state = global_state.mstate
state.stack.append(BitVecVal(0, 256))
if len(global_state.call_stack) is 0: if len(global_state.call_stack) is 0:
return [] return []
global_state.mstate.pc = global_state.call_stack.pop() new_global_state = deepcopy(global_state.call_stack.pop())
return [global_state] new_global_state.node = global_state.node
return [new_global_state]
@instruction @instruction
def call_(self, global_state): def call_(self, global_state):
@ -891,12 +891,12 @@ class Instruction:
# TODO: decide what to do in this case # TODO: decide what to do in this case
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256)) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
if 0 < int(callee_address, 16) < 5: if 0 < int(callee_address, 16) < 5:
logging.info("Native contract called: " + callee_address) logging.info("Native contract called: " + callee_address)
if call_data == [] and call_data_type == CalldataType.SYMBOLIC: if call_data == [] and call_data_type == CalldataType.SYMBOLIC:
logging.debug("CALL with symbolic data not supported") logging.debug("CALL with symbolic data not supported")
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
try: try:
@ -904,7 +904,6 @@ class Instruction:
mem_out_sz = memory_out_size.as_long() mem_out_sz = memory_out_size.as_long()
except AttributeError: except AttributeError:
logging.debug("CALL with symbolic start or offset not supported") logging.debug("CALL with symbolic start or offset not supported")
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
global_state.mstate.mem_extend(mem_out_start, mem_out_sz) global_state.mstate.mem_extend(mem_out_start, mem_out_sz)
@ -917,18 +916,14 @@ class Instruction:
global_state.mstate.memory[mem_out_start+i] = BitVec(contract_list[call_address_int - 1]+ global_state.mstate.memory[mem_out_start+i] = BitVec(contract_list[call_address_int - 1]+
"(" + str(call_data) + ")", 256) "(" + str(call_data) + ")", 256)
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
for i in range(min(len(data), mem_out_sz)): # If more data is used then it's chopped off for i in range(min(len(data), mem_out_sz)): # If more data is used then it's chopped off
global_state.mstate.memory[mem_out_start + i] = data[i] global_state.mstate.memory[mem_out_start + i] = data[i]
# TODO: maybe use BitVec here constrained to 1 # TODO: maybe use BitVec here constrained to 1
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
global_state.call_stack.append(instr['address'])
callee_environment = Environment(callee_account, callee_environment = Environment(callee_account,
BitVecVal(int(environment.active_account.address, 16), 256), BitVecVal(int(environment.active_account.address, 16), 256),
call_data, call_data,
@ -937,9 +932,11 @@ class Instruction:
environment.origin, environment.origin,
calldata_type=call_data_type) calldata_type=call_data_type)
new_global_state = GlobalState(global_state.accounts, callee_environment, global_state.node, MachineState(gas)) new_global_state = GlobalState(global_state.accounts, callee_environment, global_state.node, MachineState(gas))
new_global_state.call_stack.append(global_state)
new_global_state.mstate.pc = -1
new_global_state.mstate.depth = global_state.mstate.depth + 1 new_global_state.mstate.depth = global_state.mstate.depth + 1
new_global_state.mstate.constraints = copy(global_state.mstate.constraints) new_global_state.mstate.constraints = copy(global_state.mstate.constraints)
return [global_state] return [new_global_state]
@instruction @instruction
def callcode_(self, global_state): def callcode_(self, global_state):
@ -955,7 +952,7 @@ class Instruction:
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256)) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
global_state.call_stack.append(instr['address']) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
environment = deepcopy(environment) environment = deepcopy(environment)
@ -964,6 +961,8 @@ class Instruction:
environment.calldata = call_data environment.calldata = call_data
new_global_state = GlobalState(global_state.accounts, environment, global_state.node, MachineState(gas)) new_global_state = GlobalState(global_state.accounts, environment, global_state.node, MachineState(gas))
new_global_state.call_stack.append(global_state)
new_global_state.mstate.pc = -1
new_global_state.mstate.depth = global_state.mstate.depth + 1 new_global_state.mstate.depth = global_state.mstate.depth + 1
new_global_state.mstate.constraints = copy(global_state.mstate.constraints) new_global_state.mstate.constraints = copy(global_state.mstate.constraints)
@ -983,15 +982,16 @@ class Instruction:
global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256)) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
return [global_state] return [global_state]
global_state.call_stack.append(instr['address']) global_state.mstate.stack.append(BitVec("retval_" + str(instr['address']), 256))
environment = deepcopy(environment)
environment = deepcopy(environment) environment = deepcopy(environment)
environment.code = callee_account.code environment.code = callee_account.code
environment.calldata = call_data environment.calldata = call_data
new_global_state = GlobalState(global_state.accounts, environment, global_state.node, MachineState(gas)) new_global_state = GlobalState(global_state.accounts, environment, global_state.node, MachineState(gas))
new_global_state.call_stack.append(global_state)
new_global_state.mstate.pc = -1
new_global_state.mstate.depth = global_state.mstate.depth + 1 new_global_state.mstate.depth = global_state.mstate.depth + 1
new_global_state.mstate.constraints = copy(global_state.mstate.constraints) new_global_state.mstate.constraints = copy(global_state.mstate.constraints)

@ -137,12 +137,12 @@ class GlobalState:
self.op_code = "" self.op_code = ""
def __copy__(self): def __copy__(self):
accounts = copy(self.accounts) accounts = self.accounts
environment = copy(self.environment) environment = copy(self.environment)
mstate = deepcopy(self.mstate) mstate = deepcopy(self.mstate)
return GlobalState(accounts, environment, self.node, mstate) call_stack = copy(self.call_stack)
return GlobalState(accounts, environment, self.node, mstate, call_stack=call_stack)
#TODO: remove this, as two instructions are confusing #TODO: remove this, as two instructions are confusing
def get_current_instruction(self): def get_current_instruction(self):

@ -98,6 +98,9 @@ class LaserEVM:
def execute_state(self, global_state): def execute_state(self, global_state):
instructions = global_state.environment.code.instruction_list instructions = global_state.environment.code.instruction_list
op_code = instructions[global_state.mstate.pc]['opcode'] op_code = instructions[global_state.mstate.pc]['opcode']
# Only count coverage for the main contract
if len(global_state.call_stack) == 0:
self.instructions_covered[global_state.mstate.pc] = True self.instructions_covered[global_state.mstate.pc] = True
self._execute_pre_hook(op_code, global_state) self._execute_pre_hook(op_code, global_state)

@ -101,16 +101,29 @@ class TaintRunner:
# List of (Node, TaintRecord, index) # List of (Node, TaintRecord, index)
current_nodes = [(node, init_record, state_index)] current_nodes = [(node, init_record, state_index)]
environment = node.states[0].environment
for node, record, index in current_nodes: for node, record, index in current_nodes:
records = TaintRunner.execute_node(node, record, index) records = TaintRunner.execute_node(node, record, index)
result.add_records(records) result.add_records(records)
children = [statespace.nodes[edge.node_to] for edge in statespace.edges if edge.node_from == node.uid] children = TaintRunner.children(node, statespace, environment)
for child in children: for child in children:
current_nodes.append((child, records[-1], 0)) current_nodes.append((child, records[-1], 0))
return result return result
@staticmethod
def children(node, statespace, environment):
direct_children = [statespace.nodes[edge.node_to] for edge in statespace.edges if edge.node_from == node.uid]
children = []
for child in direct_children:
if child.states[0].environment == environment:
children.append(child)
else:
children += TaintRunner.children(child, statespace, environment)
return children
@staticmethod @staticmethod
def execute_node(node, last_record, state_index=0): def execute_node(node, last_record, state_index=0):
""" """

@ -1,15 +1,13 @@
import plyvel
import binascii import binascii
import rlp import rlp
from mythril.leveldb.accountindexing import CountableList from mythril.leveldb.accountindexing import CountableList
import hashlib from mythril.leveldb.accountindexing import ReceiptForStorage, AccountIndexer
import logging import logging
from ethereum import utils from ethereum import utils
from ethereum.block import BlockHeader, Block from ethereum.block import BlockHeader, Block
from mythril.leveldb.accountindexing import ReceiptForStorage, AccountIndexer from mythril.leveldb.state import State
from mythril.leveldb.state import State, Account
from mythril.leveldb.eth_db import ETH_DB from mythril.leveldb.eth_db import ETH_DB
from mythril.ether.ethcontract import ETHContract, InstanceList from mythril.ether.ethcontract import ETHContract
# Per https://github.com/ethereum/go-ethereum/blob/master/core/database_util.go # Per https://github.com/ethereum/go-ethereum/blob/master/core/database_util.go
# prefixes and suffixes for keys in geth # prefixes and suffixes for keys in geth
@ -24,6 +22,8 @@ headHeaderKey = b'LastBlock' # head (latest) header hash
addressPrefix = b'AM' # addressPrefix + hash -> address addressPrefix = b'AM' # addressPrefix + hash -> address
# custom keys # custom keys
addressMappingHeadKey = b'accountMapping' # head (latest) number of indexed block addressMappingHeadKey = b'accountMapping' # head (latest) number of indexed block
headHeaderKey = b'LastBlock' # head (latest) header hash
def _formatBlockNumber(number): def _formatBlockNumber(number):
''' '''
@ -31,6 +31,7 @@ def _formatBlockNumber(number):
''' '''
return utils.zpad(utils.int_to_big_endian(number), 8) return utils.zpad(utils.int_to_big_endian(number), 8)
def _encode_hex(v): def _encode_hex(v):
''' '''
encodes hash as hex encodes hash as hex

@ -19,7 +19,7 @@ import platform
from mythril.ether import util from mythril.ether import util
from mythril.ether.ethcontract import ETHContract from mythril.ether.ethcontract import ETHContract
from mythril.ether.soliditycontract import SolidityContract from mythril.ether.soliditycontract import SolidityContract, get_contracts_from_file
from mythril.rpc.client import EthJsonRpc from mythril.rpc.client import EthJsonRpc
from mythril.ipc.client import EthIpc from mythril.ipc.client import EthIpc
from mythril.rpc.exceptions import ConnectionError from mythril.rpc.exceptions import ConnectionError
@ -288,34 +288,37 @@ class Mythril(object):
# import signatures from solidity source # import signatures from solidity source
with open(file, encoding="utf-8") as f: with open(file, encoding="utf-8") as f:
self.sigs.import_from_solidity_source(f.read()) self.sigs.import_from_solidity_source(f.read())
if contract_name is not None:
contract = SolidityContract(file, contract_name, solc_args=self.solc_args) contract = SolidityContract(file, contract_name, solc_args=self.solc_args)
logging.info("Analyzing contract %s:%s" % (file, contract.name)) self.contracts.append(contract)
contracts.append(contract)
else:
for contract in get_contracts_from_file(file, solc_args=self.solc_args):
self.contracts.append(contract)
contracts.append(contract)
except FileNotFoundError: except FileNotFoundError:
raise CriticalError("Input file not found: " + file) raise CriticalError("Input file not found: " + file)
except CompilerError as e: except CompilerError as e:
raise CriticalError(e) raise CriticalError(e)
except NoContractFoundError: except NoContractFoundError:
logging.info("The file " + file + " does not contain a compilable contract.") logging.info("The file " + file + " does not contain a compilable contract.")
else:
self.contracts.append(contract)
contracts.append(contract)
# Save updated function signatures # Save updated function signatures
self.sigs.write() # dump signatures to disk (previously opened file or default location) self.sigs.write() # dump signatures to disk (previously opened file or default location)
return address, contracts return address, contracts
def dump_statespace(self, contract, address=None, max_depth=12): def dump_statespace(self, strategy, contract, address=None, max_depth=12):
sym = SymExecWrapper(contract, address, sym = SymExecWrapper(contract, address, strategy,
dynloader=DynLoader(self.eth) if self.dynld else None, dynloader=DynLoader(self.eth) if self.dynld else None,
max_depth=max_depth) max_depth=max_depth)
return get_serializable_statespace(sym) return get_serializable_statespace(sym)
def graph_html(self, contract, address, max_depth=12, enable_physics=False, phrackify=False): def graph_html(self, strategy, contract, address, max_depth=12, enable_physics=False, phrackify=False):
sym = SymExecWrapper(contract, address, sym = SymExecWrapper(contract, address, strategy,
dynloader=DynLoader(self.eth) if self.dynld else None, dynloader=DynLoader(self.eth) if self.dynld else None,
max_depth=max_depth) max_depth=max_depth)
return generate_graph(sym, physics=enable_physics, phrackify=phrackify) return generate_graph(sym, physics=enable_physics, phrackify=phrackify)

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

@ -1,13 +1,18 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
from setuptools.command.install import install from setuptools.command.install import install
from pathlib import Path
import sys import sys
import os import os
# To make lint checkers happy we set VERSION here, but
# it is redefined by the exec below
VERSION = None
# Package version (vX.Y.Z). It must match git tag being used for CircleCI # Package version (vX.Y.Z). It must match git tag being used for CircleCI
# deployment; otherwise the build will failed. # deployment; otherwise the build will failed.
VERSION = "v0.18.8" version_path = (Path(__file__).parent / 'mythril' / 'version.py').absolute()
exec(open(version_path, 'r').read())
class VerifyVersionCommand(install): class VerifyVersionCommand(install):
"""Custom command to verify that the git tag matches our version""" """Custom command to verify that the git tag matches our version"""

@ -0,0 +1,299 @@
pragma solidity ^0.4.16;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) public constant returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
*/
contract BasicToken is ERC20Basic {
using SafeMath for uint256;
mapping(address => uint256) balances;
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value > 0 && _value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
}
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) public constant returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value > 0 && _value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(_from, _to, _value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
*
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
/**
* @title Pausable token
*
* @dev StandardToken modified with pausable transfers.
**/
contract PausableToken is StandardToken, Pausable {
function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) {
return super.transfer(_to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) {
return super.transferFrom(_from, _to, _value);
}
function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) {
return super.approve(_spender, _value);
}
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
uint cnt = _receivers.length;
uint256 amount = uint256(cnt) * _value;
require(cnt > 0 && cnt <= 20);
require(_value > 0 && balances[msg.sender] >= amount);
balances[msg.sender] = balances[msg.sender].sub(amount);
for (uint i = 0; i < cnt; i++) {
balances[_receivers[i]] = balances[_receivers[i]].add(_value);
Transfer(msg.sender, _receivers[i], _value);
}
return true;
}
}
/**
* @title Bec Token
*
* @dev Implementation of Bec Token based on the basic standard token.
*/
contract BecToken is PausableToken {
/**
* Public variables of the token
* The following variables are OPTIONAL vanities. One does not have to include them.
* They allow one to customise the token contract & in no way influences the core functionality.
* Some wallets/interfaces might not even bother to look at this information.
*/
string public name = "BeautyChain";
string public symbol = "BEC";
string public version = '1.0.0';
uint8 public decimals = 18;
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
*/
function BecToken() {
totalSupply = 7000000000 * (10**(uint256(decimals)));
balances[msg.sender] = totalSupply; // Give the creator all initial tokens
}
function () {
//if ether is sent to this address, send it back.
revert();
}
}

@ -0,0 +1,396 @@
//sol Wallet
// Multi-sig, daily-limited account proxy/wallet.
// @authors:
// Gav Wood <g@ethdev.com>
// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
// single, or, crucially, each of a number of, designated owners.
// usage:
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
pragma solidity ^0.4.9;
contract WalletEvents {
// EVENTS
// this contract only has six types of events: it can accept a confirmation, in which case
// we record owner and operation (hash) alongside it.
event Confirmation(address owner, bytes32 operation);
event Revoke(address owner, bytes32 operation);
// some others are in the case of an owner changing.
event OwnerChanged(address oldOwner, address newOwner);
event OwnerAdded(address newOwner);
event OwnerRemoved(address oldOwner);
// the last one is emitted if the required signatures change
event RequirementChanged(uint newRequirement);
// Funds has arrived into the wallet (record how much).
event Deposit(address _from, uint value);
// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
event SingleTransact(address owner, uint value, address to, bytes data, address created);
// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data, address created);
// Confirmation still needed for a transaction.
event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data);
}
contract WalletAbi {
// Revokes a prior confirmation of the given operation
function revoke(bytes32 _operation) external;
// Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) external;
function addOwner(address _owner) external;
function removeOwner(address _owner) external;
function changeRequirement(uint _newRequired) external;
function isOwner(address _addr) constant returns (bool);
function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool);
// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
function setDailyLimit(uint _newLimit) external;
function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash);
function confirm(bytes32 _h) returns (bool o_success);
}
contract WalletLibrary is WalletEvents {
// TYPES
// struct for the status of a pending operation.
struct PendingState {
uint yetNeeded;
uint ownersDone;
uint index;
}
// Transaction structure to remember details of transaction lest it need be saved for a later call.
struct Transaction {
address to;
uint value;
bytes data;
}
// MODIFIERS
// simple single-sig function modifier.
modifier onlyowner {
if (isOwner(msg.sender))
_;
}
// multi-sig function modifier: the operation must have an intrinsic hash in order
// that later attempts can be realised as the same underlying operation and
// thus count as confirmations.
modifier onlymanyowners(bytes32 _operation) {
if (confirmAndCheck(_operation))
_;
}
// METHODS
// gets called when no other function matches
function() payable {
// just being sent some cash?
if (msg.value > 0)
Deposit(msg.sender, msg.value);
}
// constructor is given number of sigs required to do protected "onlymanyowners" transactions
// as well as the selection of addresses capable of confirming them.
function initMultiowned(address[] _owners, uint _required) only_uninitialized {
m_numOwners = _owners.length + 1;
m_owners[1] = uint(msg.sender);
m_ownerIndex[uint(msg.sender)] = 1;
for (uint i = 0; i < _owners.length; ++i)
{
m_owners[2 + i] = uint(_owners[i]);
m_ownerIndex[uint(_owners[i])] = 2 + i;
}
m_required = _required;
}
// Revokes a prior confirmation of the given operation
function revoke(bytes32 _operation) external {
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
// make sure they're an owner
if (ownerIndex == 0) return;
uint ownerIndexBit = 2**ownerIndex;
var pending = m_pending[_operation];
if (pending.ownersDone & ownerIndexBit > 0) {
pending.yetNeeded++;
pending.ownersDone -= ownerIndexBit;
Revoke(msg.sender, _operation);
}
}
// Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external {
if (isOwner(_to)) return;
uint ownerIndex = m_ownerIndex[uint(_from)];
if (ownerIndex == 0) return;
clearPending();
m_owners[ownerIndex] = uint(_to);
m_ownerIndex[uint(_from)] = 0;
m_ownerIndex[uint(_to)] = ownerIndex;
OwnerChanged(_from, _to);
}
function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
if (isOwner(_owner)) return;
clearPending();
if (m_numOwners >= c_maxOwners)
reorganizeOwners();
if (m_numOwners >= c_maxOwners)
return;
m_numOwners++;
m_owners[m_numOwners] = uint(_owner);
m_ownerIndex[uint(_owner)] = m_numOwners;
OwnerAdded(_owner);
}
function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external {
uint ownerIndex = m_ownerIndex[uint(_owner)];
if (ownerIndex == 0) return;
if (m_required > m_numOwners - 1) return;
m_owners[ownerIndex] = 0;
m_ownerIndex[uint(_owner)] = 0;
clearPending();
reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot
OwnerRemoved(_owner);
}
function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external {
if (_newRequired > m_numOwners) return;
m_required = _newRequired;
clearPending();
RequirementChanged(_newRequired);
}
// Gets an owner by 0-indexed position (using numOwners as the count)
function getOwner(uint ownerIndex) external constant returns (address) {
return address(m_owners[ownerIndex + 1]);
}
function isOwner(address _addr) constant returns (bool) {
return m_ownerIndex[uint(_addr)] > 0;
}
function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) {
var pending = m_pending[_operation];
uint ownerIndex = m_ownerIndex[uint(_owner)];
// make sure they're an owner
if (ownerIndex == 0) return false;
// determine the bit to set for this owner.
uint ownerIndexBit = 2**ownerIndex;
return !(pending.ownersDone & ownerIndexBit == 0);
}
// constructor - stores initial daily limit and records the present day's index.
function initDaylimit(uint _limit) only_uninitialized {
m_dailyLimit = _limit;
m_lastDay = today();
}
// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
m_dailyLimit = _newLimit;
}
// resets the amount already spent today. needs many of the owners to confirm.
function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
m_spentToday = 0;
}
// throw unless the contract is not yet initialized.
modifier only_uninitialized { if (m_numOwners > 0) throw; _; }
// constructor - just pass on the owner array to the multiowned and
// the limit to daylimit
function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
initDaylimit(_daylimit);
initMultiowned(_owners, _required);
}
// kills the contract sending everything to `_to`.
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
suicide(_to);
}
// Outside-visible transact entry point. Executes transaction immediately if below daily spend limit.
// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
// and _data arguments). They still get the option of using them if they want, anyways.
function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) {
// first, take the opportunity to check that we're under the daily limit.
if ((_data.length == 0 && underLimit(_value)) || m_required == 1) {
// yes - just execute the call.
address created;
if (_to == 0) {
created = create(_value, _data);
} else {
if (!_to.call.value(_value)(_data))
throw;
}
SingleTransact(msg.sender, _value, _to, _data, created);
} else {
// determine our operation hash.
o_hash = sha3(msg.data, block.number);
// store if it's new
if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) {
m_txs[o_hash].to = _to;
m_txs[o_hash].value = _value;
m_txs[o_hash].data = _data;
}
if (!confirm(o_hash)) {
ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data);
}
}
}
function create(uint _value, bytes _code) internal returns (address o_addr) {
assembly {
o_addr := create(_value, add(_code, 0x20), mload(_code))
jumpi(0xdeadbeef, iszero(extcodesize(o_addr)))
}
}
// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
// to determine the body of the transaction from the hash provided.
function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) {
if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) {
address created;
if (m_txs[_h].to == 0) {
created = create(m_txs[_h].value, m_txs[_h].data);
} else {
if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data))
throw;
}
MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created);
delete m_txs[_h];
return true;
}
}
// INTERNAL METHODS
function confirmAndCheck(bytes32 _operation) internal returns (bool) {
// determine what index the present sender is:
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
// make sure they're an owner
if (ownerIndex == 0) return;
var pending = m_pending[_operation];
// if we're not yet working on this operation, switch over and reset the confirmation status.
if (pending.yetNeeded == 0) {
// reset count of confirmations needed.
pending.yetNeeded = m_required;
// reset which owners have confirmed (none) - set our bitmap to 0.
pending.ownersDone = 0;
pending.index = m_pendingIndex.length++;
m_pendingIndex[pending.index] = _operation;
}
// determine the bit to set for this owner.
uint ownerIndexBit = 2**ownerIndex;
// make sure we (the message sender) haven't confirmed this operation previously.
if (pending.ownersDone & ownerIndexBit == 0) {
Confirmation(msg.sender, _operation);
// ok - check if count is enough to go ahead.
if (pending.yetNeeded <= 1) {
// enough confirmations: reset and run interior.
delete m_pendingIndex[m_pending[_operation].index];
delete m_pending[_operation];
return true;
}
else
{
// not enough: record that this owner in particular confirmed.
pending.yetNeeded--;
pending.ownersDone |= ownerIndexBit;
}
}
}
function reorganizeOwners() private {
uint free = 1;
while (free < m_numOwners)
{
while (free < m_numOwners && m_owners[free] != 0) free++;
while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--;
if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0)
{
m_owners[free] = m_owners[m_numOwners];
m_ownerIndex[m_owners[free]] = free;
m_owners[m_numOwners] = 0;
}
}
}
// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
// returns true. otherwise just returns false.
function underLimit(uint _value) internal onlyowner returns (bool) {
// reset the spend limit if we're on a different day to last time.
if (today() > m_lastDay) {
m_spentToday = 0;
m_lastDay = today();
}
// check to see if there's enough left - if so, subtract and return true.
// overflow protection // dailyLimit check
if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) {
m_spentToday += _value;
return true;
}
return false;
}
// determines today's index.
function today() private constant returns (uint) { return now / 1 days; }
function clearPending() internal {
uint length = m_pendingIndex.length;
for (uint i = 0; i < length; ++i) {
delete m_txs[m_pendingIndex[i]];
if (m_pendingIndex[i] != 0)
delete m_pending[m_pendingIndex[i]];
}
delete m_pendingIndex;
}
// FIELDS
address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe;
// the number of owners that must confirm the same operation before it is run.
uint public m_required;
// pointer used to find a free slot in m_owners
uint public m_numOwners;
uint public m_dailyLimit;
uint public m_spentToday;
uint public m_lastDay;
// list of owners
uint[256] m_owners;
uint constant c_maxOwners = 250;
// index on the list of owners to allow reverse lookup
mapping(uint => uint) m_ownerIndex;
// the ongoing operations.
mapping(bytes32 => PendingState) m_pending;
bytes32[] m_pendingIndex;
// pending transactions we have at present.
mapping (bytes32 => Transaction) m_txs;
}

@ -1,31 +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];
}
}

@ -0,0 +1,21 @@
contract EtherStore {
uint256 public withdrawalLimit = 1 ether;
mapping(address => uint256) public lastWithdrawTime;
mapping(address => uint256) public balances;
function depositFunds() public payable {
balances[msg.sender] += msg.value;
}
function withdrawFunds (uint256 _weiToWithdraw) public {
require(balances[msg.sender] >= _weiToWithdraw);
// limit the withdrawal
require(_weiToWithdraw <= withdrawalLimit);
// limit the time allowed to withdraw
require(now >= lastWithdrawTime[msg.sender] + 1 weeks);
require(msg.sender.call.value(_weiToWithdraw)());
balances[msg.sender] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = now;
}
}

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

@ -0,0 +1,21 @@
contract TimeLock {
mapping(address => uint) public balances;
mapping(address => uint) public lockTime;
function deposit() public payable {
balances[msg.sender] += msg.value;
lockTime[msg.sender] = now + 1 weeks;
}
function increaseLockTime(uint _secondsToIncrease) public {
lockTime[msg.sender] += _secondsToIncrease;
}
function withdraw() public {
require(balances[msg.sender] > 0);
require(now > lockTime[msg.sender]);
balances[msg.sender] = 0;
msg.sender.transfer(balances[msg.sender]);
}
}

@ -1,4 +1,6 @@
contract Under { pragma solidity ^0.4.18;
contract Token {
mapping(address => uint) balances; mapping(address => uint) balances;
uint public totalSupply; uint public totalSupply;
@ -7,7 +9,7 @@ contract Under {
balances[msg.sender] = totalSupply = _initialSupply; balances[msg.sender] = totalSupply = _initialSupply;
} }
function sendeth(address _to, uint _value) public returns (bool) { function transfer(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0); require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value; balances[msg.sender] -= _value;
balances[_to] += _value; balances[_to] += _value;
Loading…
Cancel
Save