mirror of https://github.com/ConsenSys/mythril
commit
6128931242
@ -1,2 +1,5 @@ |
||||
tests/testdata/* linguist-detectable=false |
||||
static/* linguist-documentation |
||||
static/* linguist-documentation |
||||
|
||||
# Solidity |
||||
*.sol linguist-language=Solidity |
||||
|
@ -1,2 +1,2 @@ |
||||
include mythril/disassembler/signatures.json |
||||
include mythril/disassembler/signatures.db |
||||
include mythril/analysis/templates/* |
||||
|
@ -1,47 +0,0 @@ |
||||
import re |
||||
from typing import List |
||||
from z3 import * |
||||
from mythril.laser.ethereum.transaction import ContractCreationTransaction |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
|
||||
|
||||
def get_non_creator_constraints(state: GlobalState) -> (List, bool): |
||||
""" |
||||
Get constraints which say that the caller isn't the creator of the contract |
||||
:param state: The state |
||||
:return: tuple of (constraints, bool) where the bool says whether the caller is constrained or not |
||||
""" |
||||
not_creator_constraints = [] |
||||
creator = None |
||||
if isinstance( |
||||
state.world_state.transaction_sequence[0], ContractCreationTransaction |
||||
): |
||||
creator = state.world_state.transaction_sequence[0].caller |
||||
if creator is not None: |
||||
for transaction in state.world_state.transaction_sequence[1:]: |
||||
not_creator_constraints.append( |
||||
Not(Extract(159, 0, transaction.caller) == Extract(159, 0, creator)) |
||||
) |
||||
not_creator_constraints.append( |
||||
Not(Extract(159, 0, transaction.caller) == 0) |
||||
) |
||||
else: |
||||
for transaction in state.world_state.transaction_sequence: |
||||
not_creator_constraints.append( |
||||
Not(Extract(159, 0, transaction.caller) == 0) |
||||
) |
||||
if not has_caller_check_constraint(state.mstate.constraints): |
||||
return [], True |
||||
return not_creator_constraints, False |
||||
|
||||
|
||||
def has_caller_check_constraint(constraints: List) -> bool: |
||||
""" |
||||
Checks whether the caller is constrained to a value or not |
||||
""" |
||||
for constraint in constraints: |
||||
if re.search(r"caller", str(constraint)) and re.search( |
||||
r"[0-9]{20}", str(constraint) |
||||
): |
||||
return False |
||||
return True |
@ -1,218 +1,111 @@ |
||||
from z3 import * |
||||
from mythril.analysis.ops import * |
||||
from mythril.analysis.report import Issue |
||||
from mythril.analysis import solver |
||||
from mythril.analysis.swc_data import REENTRANCY |
||||
from mythril.analysis.modules.base import DetectionModule |
||||
import re |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
from mythril.exceptions import UnsatError |
||||
import logging |
||||
from mythril.laser.ethereum.cfg import JumpType |
||||
|
||||
DESCRIPTION = """ |
||||
|
||||
class ExternalCallModule(DetectionModule): |
||||
def __init__(self, max_search_depth=64): |
||||
Search for low level calls (e.g. call.value()) that forward all gas to the callee. |
||||
Report a warning if the callee address can be set by the sender, otherwise create |
||||
an informational issue. |
||||
|
||||
""" |
||||
|
||||
|
||||
def _analyze_state(state): |
||||
|
||||
node = state.node |
||||
gas = state.mstate.stack[-1] |
||||
to = state.mstate.stack[-2] |
||||
|
||||
address = state.get_current_instruction()["address"] |
||||
|
||||
try: |
||||
constraints = node.constraints |
||||
transaction_sequence = solver.get_transaction_sequence( |
||||
state, constraints + [UGT(gas, 2300)] |
||||
) |
||||
|
||||
# Check whether we can also set the callee address |
||||
|
||||
try: |
||||
constraints += [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF] |
||||
transaction_sequence = solver.get_transaction_sequence(state, constraints) |
||||
|
||||
debug = str(transaction_sequence) |
||||
description = ( |
||||
"The contract executes a function call with high gas to a user-supplied address. " |
||||
"Note that the callee can contain arbitrary code and may re-enter any function in this contract. " |
||||
"Review the business logic carefully to prevent unanticipated effects on the contract state." |
||||
) |
||||
|
||||
issue = Issue( |
||||
contract=node.contract_name, |
||||
function_name=node.function_name, |
||||
address=address, |
||||
swc_id=REENTRANCY, |
||||
title="External call to user-supplied address", |
||||
_type="Warning", |
||||
bytecode=state.environment.code.bytecode, |
||||
description=description, |
||||
debug=debug, |
||||
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), |
||||
) |
||||
|
||||
except UnsatError: |
||||
|
||||
logging.debug( |
||||
"[EXTERNAL_CALLS] Callee address cannot be modified. Reporting informational issue." |
||||
) |
||||
|
||||
debug = str(transaction_sequence) |
||||
description = ( |
||||
"The contract executes a function call to an external address. " |
||||
"Verify that the code at this address is trusted and immutable." |
||||
) |
||||
|
||||
issue = Issue( |
||||
contract=node.contract_name, |
||||
function_name=state.node.function_name, |
||||
address=address, |
||||
swc_id=REENTRANCY, |
||||
title="External call", |
||||
_type="Informational", |
||||
bytecode=state.environment.code.bytecode, |
||||
description=description, |
||||
debug=debug, |
||||
gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), |
||||
) |
||||
|
||||
except UnsatError: |
||||
logging.debug("[EXTERNAL_CALLS] No model found.") |
||||
return [] |
||||
|
||||
return [issue] |
||||
|
||||
|
||||
class ExternalCalls(DetectionModule): |
||||
def __init__(self): |
||||
super().__init__( |
||||
name="External Calls", |
||||
name="External calls", |
||||
swc_id=REENTRANCY, |
||||
hooks=["CALL"], |
||||
description="Check for call.value()() to external addresses", |
||||
description=(DESCRIPTION), |
||||
entrypoint="callback", |
||||
) |
||||
self.max_search_depth = max_search_depth |
||||
self.calls_visited = [] |
||||
|
||||
def search_children( |
||||
self, statespace, node, transaction_id, start_index=0, depth=0, results=None |
||||
): |
||||
if results is None: |
||||
results = [] |
||||
logging.debug("SEARCHING NODE %d", node.uid) |
||||
|
||||
if depth < self.max_search_depth: |
||||
|
||||
n_states = len(node.states) |
||||
|
||||
if n_states > start_index: |
||||
|
||||
for j in range(start_index, n_states): |
||||
if ( |
||||
node.states[j].get_current_instruction()["opcode"] == "SSTORE" |
||||
and node.states[j].current_transaction.id == transaction_id |
||||
): |
||||
results.append( |
||||
node.states[j].get_current_instruction()["address"] |
||||
) |
||||
children = [] |
||||
|
||||
for edge in statespace.edges: |
||||
if edge.node_from == node.uid and edge.type != JumpType.Transaction: |
||||
children.append(statespace.nodes[edge.node_to]) |
||||
|
||||
if len(children): |
||||
for node in children: |
||||
results += self.search_children( |
||||
statespace, |
||||
node, |
||||
transaction_id, |
||||
depth=depth + 1, |
||||
results=results, |
||||
) |
||||
|
||||
return results |
||||
|
||||
def execute(self, statespace): |
||||
|
||||
issues = [] |
||||
|
||||
for call in statespace.calls: |
||||
|
||||
state = call.state |
||||
address = state.get_current_instruction()["address"] |
||||
|
||||
if call.type == "CALL": |
||||
|
||||
logging.debug( |
||||
"[EXTERNAL_CALLS] Call to: %s, value = %s, gas = %s" |
||||
% (str(call.to), str(call.value), str(call.gas)) |
||||
) |
||||
|
||||
if ( |
||||
call.to.type == VarType.SYMBOLIC |
||||
and (call.gas.type == VarType.CONCRETE and call.gas.val > 2300) |
||||
or ( |
||||
call.gas.type == VarType.SYMBOLIC |
||||
and "2300" not in str(call.gas) |
||||
) |
||||
): |
||||
|
||||
description = "This contract executes a message call to " |
||||
|
||||
target = str(call.to) |
||||
user_supplied = False |
||||
|
||||
if "calldata" in target or "caller" in target: |
||||
|
||||
if "calldata" in target: |
||||
description += ( |
||||
"an address provided as a function argument. " |
||||
) |
||||
else: |
||||
description += "the address of the transaction sender. " |
||||
|
||||
user_supplied = True |
||||
else: |
||||
m = re.search(r"storage_([a-z0-9_&^]+)", str(call.to)) |
||||
|
||||
if m: |
||||
idx = m.group(1) |
||||
|
||||
func = statespace.find_storage_write( |
||||
state.environment.active_account.address, idx |
||||
) |
||||
|
||||
if func: |
||||
|
||||
description += ( |
||||
"an address found at storage slot " |
||||
+ str(idx) |
||||
+ ". " |
||||
+ "This storage slot can be written to by calling the function `" |
||||
+ func |
||||
+ "`. " |
||||
) |
||||
user_supplied = True |
||||
|
||||
if user_supplied: |
||||
|
||||
description += ( |
||||
"Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. " |
||||
"Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state." |
||||
) |
||||
|
||||
issue = Issue( |
||||
contract=call.node.contract_name, |
||||
function_name=call.node.function_name, |
||||
address=address, |
||||
title="Message call to external contract", |
||||
_type="Warning", |
||||
description=description, |
||||
bytecode=state.environment.code.bytecode, |
||||
swc_id=REENTRANCY, |
||||
gas_used=( |
||||
state.mstate.min_gas_used, |
||||
state.mstate.max_gas_used, |
||||
), |
||||
) |
||||
|
||||
else: |
||||
|
||||
description += "to another contract. Make sure that the called contract is trusted and does not execute user-supplied code." |
||||
|
||||
issue = Issue( |
||||
contract=call.node.contract_name, |
||||
function_name=call.node.function_name, |
||||
address=address, |
||||
title="Message call to external contract", |
||||
_type="Informational", |
||||
description=description, |
||||
bytecode=state.environment.code.bytecode, |
||||
swc_id=REENTRANCY, |
||||
gas_used=( |
||||
state.mstate.min_gas_used, |
||||
state.mstate.max_gas_used, |
||||
), |
||||
) |
||||
|
||||
issues.append(issue) |
||||
|
||||
if address not in self.calls_visited: |
||||
self.calls_visited.append(address) |
||||
|
||||
logging.debug( |
||||
"[EXTERNAL_CALLS] Checking for state changes starting from " |
||||
+ call.node.function_name |
||||
) |
||||
|
||||
# Check for SSTORE in remaining instructions in current node & nodes down the CFG |
||||
|
||||
state_change_addresses = self.search_children( |
||||
statespace, |
||||
call.node, |
||||
call.state.current_transaction.id, |
||||
call.state_index + 1, |
||||
depth=0, |
||||
results=[], |
||||
) |
||||
|
||||
logging.debug( |
||||
"[EXTERNAL_CALLS] Detected state changes at addresses: " |
||||
+ str(state_change_addresses) |
||||
) |
||||
|
||||
if len(state_change_addresses): |
||||
for address in state_change_addresses: |
||||
description = ( |
||||
"The contract account state is changed after an external call. " |
||||
"Consider that the called contract could re-enter the function before this " |
||||
"state change takes place. This can lead to business logic vulnerabilities." |
||||
) |
||||
|
||||
issue = Issue( |
||||
contract=call.node.contract_name, |
||||
function_name=call.node.function_name, |
||||
address=address, |
||||
title="State change after external call", |
||||
_type="Warning", |
||||
description=description, |
||||
bytecode=state.environment.code.bytecode, |
||||
swc_id=REENTRANCY, |
||||
gas_used=( |
||||
state.mstate.min_gas_used, |
||||
state.mstate.max_gas_used, |
||||
), |
||||
) |
||||
issues.append(issue) |
||||
|
||||
return issues |
||||
|
||||
|
||||
detector = ExternalCallModule() |
||||
self._issues = [] |
||||
|
||||
def execute(self, state: GlobalState): |
||||
self._issues.extend(_analyze_state(state)) |
||||
return self.issues |
||||
|
||||
@property |
||||
def issues(self): |
||||
return self._issues |
||||
|
||||
|
||||
detector = ExternalCalls() |
||||
|
@ -1,3 +0,0 @@ |
||||
import time |
||||
|
||||
start_time = time.time() |
@ -1,65 +0,0 @@ |
||||
from ethereum import vm, messages, transactions |
||||
from ethereum.state import State |
||||
from ethereum.slogging import get_logger |
||||
from mythril.ether import util |
||||
from logging import StreamHandler |
||||
from io import StringIO |
||||
import re |
||||
|
||||
|
||||
def trace(code, calldata=""): |
||||
log_handlers = [ |
||||
"eth.vm.op", |
||||
"eth.vm.op.stack", |
||||
"eth.vm.op.memory", |
||||
"eth.vm.op.storage", |
||||
] |
||||
output = StringIO() |
||||
stream_handler = StreamHandler(output) |
||||
|
||||
for handler in log_handlers: |
||||
log_vm_op = get_logger(handler) |
||||
log_vm_op.setLevel("TRACE") |
||||
log_vm_op.addHandler(stream_handler) |
||||
|
||||
addr = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF01234567") |
||||
state = State() |
||||
|
||||
ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr, 0, addr)) |
||||
message = vm.Message(addr, addr, 0, 21000, calldata) |
||||
vm.vm_execute(ext, message, util.safe_decode(code)) |
||||
stream_handler.flush() |
||||
ret = output.getvalue() |
||||
lines = ret.split("\n") |
||||
|
||||
state_trace = [] |
||||
for line in lines: |
||||
m = re.search(r"pc=b\'(\d+)\'.*op=([A-Z0-9]+)", line) |
||||
if m: |
||||
pc = m.group(1) |
||||
op = m.group(2) |
||||
m = re.match(r".*stack=(\[.*?\])", line) |
||||
|
||||
if m: |
||||
stackitems = re.findall(r"b\'(\d+)\'", m.group(1)) |
||||
stack = "[" |
||||
|
||||
if len(stackitems): |
||||
for i in range(0, len(stackitems) - 1): |
||||
stack += hex(int(stackitems[i])) + ", " |
||||
stack += hex(int(stackitems[-1])) |
||||
|
||||
stack += "]" |
||||
else: |
||||
stack = "[]" |
||||
|
||||
if re.match(r"^PUSH.*", op): |
||||
val = re.search(r"pushvalue=(\d+)", line).group(1) |
||||
pushvalue = hex(int(val)) |
||||
state_trace.append( |
||||
{"pc": pc, "op": op, "stack": stack, "pushvalue": pushvalue} |
||||
) |
||||
else: |
||||
state_trace.append({"pc": pc, "op": op, "stack": stack}) |
||||
|
||||
return state_trace |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,15 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract HashForEther { |
||||
|
||||
function withdrawWinnings() { |
||||
// Winner if the last 8 hex characters of the address are 0. |
||||
function withdrawWinnings() public { |
||||
// Winner if the last 8 hex characters of the address are 0. |
||||
require(uint32(msg.sender) == 0); |
||||
_sendWinnings(); |
||||
} |
||||
|
||||
function _sendWinnings() { |
||||
msg.sender.transfer(this.balance); |
||||
function _sendWinnings() public { |
||||
msg.sender.transfer(address(this).balance); |
||||
} |
||||
} |
@ -1,13 +1,17 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract ReturnValue { |
||||
|
||||
address callee = 0xE0F7e56e62b4267062172495D7506087205A4229; |
||||
address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229; |
||||
|
||||
function callnotchecked() { |
||||
callee.call(); |
||||
function callnotchecked() public { |
||||
callee.call(""); |
||||
} |
||||
|
||||
function callchecked() { |
||||
require(callee.call()); |
||||
function callchecked() public { |
||||
(bool success, bytes memory data) = callee.call(""); |
||||
require(success); |
||||
} |
||||
|
||||
} |
@ -1,152 +1,152 @@ |
||||
contract Rubixi { |
||||
|
||||
//Declare variables for storage critical to contract |
||||
uint private balance = 0; |
||||
uint private collectedFees = 0; |
||||
uint private feePercent = 10; |
||||
uint private pyramidMultiplier = 300; |
||||
uint private payoutOrder = 0; |
||||
|
||||
address private creator; |
||||
|
||||
//Sets creator |
||||
function DynamicPyramid() { |
||||
creator = msg.sender; |
||||
} |
||||
|
||||
modifier onlyowner { |
||||
if (msg.sender == creator) _; |
||||
} |
||||
|
||||
struct Participant { |
||||
address etherAddress; |
||||
uint payout; |
||||
} |
||||
|
||||
Participant[] private participants; |
||||
pragma solidity 0.5.0; |
||||
|
||||
//Fallback function |
||||
function() payable { |
||||
init(); |
||||
} |
||||
|
||||
//init function run on fallback |
||||
function init() private { |
||||
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid |
||||
if (msg.value < 1 ether) { |
||||
collectedFees += msg.value; |
||||
return; |
||||
} |
||||
|
||||
uint _fee = feePercent; |
||||
//50% fee rebate on any ether value of 50 or greater |
||||
if (msg.value >= 50 ether) _fee /= 2; |
||||
|
||||
addPayout(_fee); |
||||
} |
||||
|
||||
//Function called for valid tx to the contract |
||||
function addPayout(uint _fee) private { |
||||
//Adds new address to participant array |
||||
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100)); |
||||
|
||||
//These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan |
||||
if (participants.length == 10) pyramidMultiplier = 200; |
||||
else if (participants.length == 25) pyramidMultiplier = 150; |
||||
|
||||
// collect fees and update contract balance |
||||
balance += (msg.value * (100 - _fee)) / 100; |
||||
collectedFees += (msg.value * _fee) / 100; |
||||
|
||||
//Pays earlier participiants if balance sufficient |
||||
while (balance > participants[payoutOrder].payout) { |
||||
uint payoutToSend = participants[payoutOrder].payout; |
||||
participants[payoutOrder].etherAddress.send(payoutToSend); |
||||
|
||||
balance -= participants[payoutOrder].payout; |
||||
payoutOrder += 1; |
||||
} |
||||
} |
||||
contract Rubixi { |
||||
//Declare variables for storage critical to contract |
||||
uint private balance = 0; |
||||
uint private collectedFees = 0; |
||||
uint private feePercent = 10; |
||||
uint private pyramidMultiplier = 300; |
||||
uint private payoutOrder = 0; |
||||
|
||||
address payable private creator; |
||||
|
||||
modifier onlyowner { |
||||
if (msg.sender == creator) _; |
||||
} |
||||
|
||||
struct Participant { |
||||
address payable etherAddress; |
||||
uint payout; |
||||
} |
||||
|
||||
//Fallback function |
||||
function() external payable { |
||||
init(); |
||||
} |
||||
|
||||
//Sets creator |
||||
function dynamicPyramid() public { |
||||
creator = msg.sender; |
||||
} |
||||
|
||||
Participant[] private participants; |
||||
|
||||
//Fee functions for creator |
||||
function collectAllFees() public onlyowner { |
||||
require(collectedFees == 0); |
||||
creator.transfer(collectedFees); |
||||
collectedFees = 0; |
||||
} |
||||
|
||||
function collectFeesInEther(uint _amt) public onlyowner { |
||||
_amt *= 1 ether; |
||||
if (_amt > collectedFees) collectAllFees(); |
||||
|
||||
require(collectedFees == 0); |
||||
|
||||
creator.transfer(_amt); |
||||
collectedFees -= _amt; |
||||
} |
||||
|
||||
function collectPercentOfFees(uint _pcent) public onlyowner { |
||||
require(collectedFees == 0 || _pcent > 100); |
||||
|
||||
uint feesToCollect = collectedFees / 100 * _pcent; |
||||
creator.transfer(feesToCollect); |
||||
collectedFees -= feesToCollect; |
||||
} |
||||
|
||||
//Functions for changing variables related to the contract |
||||
function changeOwner(address payable _owner) public onlyowner { |
||||
creator = _owner; |
||||
} |
||||
|
||||
function changeMultiplier(uint _mult) public onlyowner { |
||||
require(_mult > 300 || _mult < 120); |
||||
pyramidMultiplier = _mult; |
||||
} |
||||
|
||||
function changeFeePercentage(uint _fee) public onlyowner { |
||||
require(_fee > 10); |
||||
feePercent = _fee; |
||||
} |
||||
|
||||
//Functions to provide information to end-user using JSON interface or other interfaces |
||||
function currentMultiplier() public view returns (uint multiplier, string memory info) { |
||||
multiplier = pyramidMultiplier; |
||||
info = "This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min."; |
||||
} |
||||
|
||||
function currentFeePercentage() public view returns (uint fee, string memory info) { |
||||
fee = feePercent; |
||||
info = "Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)"; |
||||
} |
||||
|
||||
//Fee functions for creator |
||||
function collectAllFees() onlyowner { |
||||
if (collectedFees == 0) throw; |
||||
function currentPyramidBalanceApproximately() public view returns (uint pyramidBalance, string memory info) { |
||||
pyramidBalance = balance / 1 ether; |
||||
info = "All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to"; |
||||
} |
||||
|
||||
creator.send(collectedFees); |
||||
collectedFees = 0; |
||||
} |
||||
function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) { |
||||
balancePayout = participants[payoutOrder].payout / 1 ether; |
||||
} |
||||
|
||||
function collectFeesInEther(uint _amt) onlyowner { |
||||
_amt *= 1 ether; |
||||
if (_amt > collectedFees) collectAllFees(); |
||||
function feesSeperateFromBalanceApproximately() public view returns (uint fees) { |
||||
fees = collectedFees / 1 ether; |
||||
} |
||||
|
||||
if (collectedFees == 0) throw; |
||||
|
||||
creator.send(_amt); |
||||
collectedFees -= _amt; |
||||
} |
||||
function totalParticipants() public view returns (uint count) { |
||||
count = participants.length; |
||||
} |
||||
|
||||
function collectPercentOfFees(uint _pcent) onlyowner { |
||||
if (collectedFees == 0 || _pcent > 100) throw; |
||||
function numberOfParticipantsWaitingForPayout() public view returns (uint count) { |
||||
count = participants.length - payoutOrder; |
||||
} |
||||
|
||||
uint feesToCollect = collectedFees / 100 * _pcent; |
||||
creator.send(feesToCollect); |
||||
collectedFees -= feesToCollect; |
||||
function participantDetails(uint orderInPyramid) public view returns (address addr, uint payout) { |
||||
if (orderInPyramid <= participants.length) { |
||||
addr = participants[orderInPyramid].etherAddress; |
||||
payout = participants[orderInPyramid].payout / 1 ether; |
||||
} |
||||
} |
||||
|
||||
//Functions for changing variables related to the contract |
||||
function changeOwner(address _owner) onlyowner { |
||||
creator = _owner; |
||||
//init function run on fallback |
||||
function init() private { |
||||
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid |
||||
if (msg.value < 1 ether) { |
||||
collectedFees += msg.value; |
||||
return; |
||||
} |
||||
|
||||
function changeMultiplier(uint _mult) onlyowner { |
||||
if (_mult > 300 || _mult < 120) throw; |
||||
uint _fee = feePercent; |
||||
// 50% fee rebate on any ether value of 50 or greater |
||||
if (msg.value >= 50 ether) _fee /= 2; |
||||
|
||||
pyramidMultiplier = _mult; |
||||
} |
||||
addPayout(_fee); |
||||
} |
||||
|
||||
function changeFeePercentage(uint _fee) onlyowner { |
||||
if (_fee > 10) throw; |
||||
//Function called for valid tx to the contract |
||||
function addPayout(uint _fee) private { |
||||
//Adds new address to participant array |
||||
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100)); |
||||
|
||||
feePercent = _fee; |
||||
} |
||||
// These statements ensure a quicker payout system to |
||||
// later pyramid entrants, so the pyramid has a longer lifespan |
||||
if (participants.length == 10) pyramidMultiplier = 200; |
||||
else if (participants.length == 25) pyramidMultiplier = 150; |
||||
|
||||
//Functions to provide information to end-user using JSON interface or other interfaces |
||||
function currentMultiplier() constant returns(uint multiplier, string info) { |
||||
multiplier = pyramidMultiplier; |
||||
info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.'; |
||||
} |
||||
|
||||
function currentFeePercentage() constant returns(uint fee, string info) { |
||||
fee = feePercent; |
||||
info = 'Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)'; |
||||
} |
||||
// collect fees and update contract balance |
||||
balance += (msg.value * (100 - _fee)) / 100; |
||||
collectedFees += (msg.value * _fee) / 100; |
||||
|
||||
function currentPyramidBalanceApproximately() constant returns(uint pyramidBalance, string info) { |
||||
pyramidBalance = balance / 1 ether; |
||||
info = 'All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to'; |
||||
} |
||||
|
||||
function nextPayoutWhenPyramidBalanceTotalsApproximately() constant returns(uint balancePayout) { |
||||
balancePayout = participants[payoutOrder].payout / 1 ether; |
||||
} |
||||
|
||||
function feesSeperateFromBalanceApproximately() constant returns(uint fees) { |
||||
fees = collectedFees / 1 ether; |
||||
} |
||||
|
||||
function totalParticipants() constant returns(uint count) { |
||||
count = participants.length; |
||||
} |
||||
|
||||
function numberOfParticipantsWaitingForPayout() constant returns(uint count) { |
||||
count = participants.length - payoutOrder; |
||||
} |
||||
//Pays earlier participiants if balance sufficient |
||||
while (balance > participants[payoutOrder].payout) { |
||||
uint payoutToSend = participants[payoutOrder].payout; |
||||
participants[payoutOrder].etherAddress.transfer(payoutToSend); |
||||
|
||||
function participantDetails(uint orderInPyramid) constant returns(address Address, uint Payout) { |
||||
if (orderInPyramid <= participants.length) { |
||||
Address = participants[orderInPyramid].etherAddress; |
||||
Payout = participants[orderInPyramid].payout / 1 ether; |
||||
} |
||||
balance -= participants[payoutOrder].payout; |
||||
payoutOrder += 1; |
||||
} |
||||
} |
||||
} |
||||
|
@ -1,6 +1,9 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract Suicide { |
||||
|
||||
function kill(address addr) { |
||||
function kill(address payable addr) public { |
||||
selfdestruct(addr); |
||||
} |
||||
|
||||
|
@ -1,268 +0,0 @@ |
||||
from mythril.analysis.modules.delegatecall import detector |
||||
from mythril.analysis.ops import Call, Variable, VarType |
||||
from mythril.analysis.symbolic import SymExecWrapper |
||||
from mythril.laser.ethereum.cfg import Node |
||||
from mythril.laser.ethereum.state.environment import Environment |
||||
from mythril.laser.ethereum.state.account import Account |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
import pytest |
||||
from unittest.mock import MagicMock, patch |
||||
import pytest_mock |
||||
from mythril.disassembler.disassembly import Disassembly |
||||
|
||||
|
||||
def test_concrete_call(): |
||||
# arrange |
||||
address = "0x10" |
||||
active_account = Account(address) |
||||
active_account.code = Disassembly("00") |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
|
||||
state = GlobalState(None, environment, None) |
||||
state.mstate.memory = ["placeholder", "calldata_bling_0"] |
||||
|
||||
node = Node("example") |
||||
node.contract_name = "the contract name" |
||||
node.function_name = "the function name" |
||||
|
||||
to = Variable(1, VarType.CONCRETE) |
||||
meminstart = Variable(1, VarType.CONCRETE) |
||||
call = Call(node, state, None, None, to, None) |
||||
|
||||
# act |
||||
issues = detector._concrete_call(call, state, address, meminstart) |
||||
|
||||
# assert |
||||
issue = issues[0] |
||||
assert issue.address == address |
||||
assert issue.contract == node.contract_name |
||||
assert issue.function == node.function_name |
||||
assert issue.title == "Call data forwarded with delegatecall()" |
||||
assert issue.type == "Informational" |
||||
assert ( |
||||
issue.description |
||||
== "This contract forwards its call data via DELEGATECALL in its fallback function." |
||||
" This means that any function in the called contract can be executed." |
||||
" Note that the callee contract will have access to the storage of the " |
||||
"calling contract.\nDELEGATECALL target: 0x1" |
||||
) |
||||
|
||||
|
||||
def test_concrete_call_symbolic_to(): |
||||
# arrange |
||||
address = "0x10" |
||||
|
||||
active_account = Account(address) |
||||
active_account.code = Disassembly("00") |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None) |
||||
state.mstate.memory = ["placeholder", "calldata_bling_0"] |
||||
|
||||
node = Node("example") |
||||
node.contract_name = "the contract name" |
||||
node.function_name = "the function name" |
||||
|
||||
to = Variable("calldata_3", VarType.SYMBOLIC) |
||||
meminstart = Variable(1, VarType.CONCRETE) |
||||
call = Call(node, state, None, None, to, None) |
||||
|
||||
# act |
||||
issues = detector._concrete_call(call, state, address, meminstart) |
||||
|
||||
# assert |
||||
issue = issues[0] |
||||
assert issue.address == address |
||||
assert issue.contract == node.contract_name |
||||
assert issue.function == node.function_name |
||||
assert issue.title == "Call data forwarded with delegatecall()" |
||||
assert issue.type == "Informational" |
||||
assert issue.description == ( |
||||
"This contract forwards its call data via DELEGATECALL in its fallback function." |
||||
" This means that any function in the called contract can be executed." |
||||
" Note that the callee contract will have access to the storage of the " |
||||
"calling contract.\nDELEGATECALL target: calldata_3" |
||||
) |
||||
|
||||
|
||||
def test_concrete_call_not_calldata(): |
||||
# arrange |
||||
state = GlobalState(None, None, None) |
||||
state.mstate.memory = ["placeholder", "not_calldata"] |
||||
meminstart = Variable(1, VarType.CONCRETE) |
||||
|
||||
# act |
||||
issues = detector._concrete_call(None, state, None, meminstart) |
||||
|
||||
# assert |
||||
assert issues == [] |
||||
|
||||
|
||||
def test_symbolic_call_storage_to(mocker): |
||||
# arrange |
||||
address = "0x10" |
||||
|
||||
active_account = Account(address) |
||||
active_account.code = Disassembly("00") |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None) |
||||
state.mstate.memory = ["placeholder", "calldata_bling_0"] |
||||
|
||||
node = Node("example") |
||||
node.contract_name = "the contract name" |
||||
node.function_name = "the function name" |
||||
|
||||
to = Variable("storage_1", VarType.SYMBOLIC) |
||||
call = Call(node, state, None, "Type: ", to, None) |
||||
|
||||
mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None) |
||||
statespace = SymExecWrapper(1) |
||||
|
||||
mocker.patch.object(statespace, "find_storage_write") |
||||
statespace.find_storage_write.return_value = "Function name" |
||||
|
||||
# act |
||||
issues = detector._symbolic_call(call, state, address, statespace) |
||||
|
||||
# assert |
||||
issue = issues[0] |
||||
assert issue.address == address |
||||
assert issue.contract == node.contract_name |
||||
assert issue.function == node.function_name |
||||
assert issue.title == "Type: to a user-supplied address" |
||||
assert issue.type == "Informational" |
||||
assert issue.description == ( |
||||
"This contract delegates execution to a contract address in storage slot 1." |
||||
" This storage slot can be written to by calling the function `Function name`." |
||||
" Be aware that the called contract gets unrestricted access to this contract's state." |
||||
) |
||||
|
||||
|
||||
def test_symbolic_call_calldata_to(mocker): |
||||
# arrange |
||||
address = "0x10" |
||||
|
||||
active_account = Account(address) |
||||
active_account.code = Disassembly("00") |
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, None) |
||||
state.mstate.memory = ["placeholder", "calldata_bling_0"] |
||||
|
||||
node = Node("example") |
||||
node.contract_name = "the contract name" |
||||
node.function_name = "the function name" |
||||
|
||||
to = Variable("calldata", VarType.SYMBOLIC) |
||||
call = Call(node, state, None, "Type: ", to, None) |
||||
|
||||
mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None) |
||||
statespace = SymExecWrapper(1) |
||||
|
||||
mocker.patch.object(statespace, "find_storage_write") |
||||
statespace.find_storage_write.return_value = "Function name" |
||||
|
||||
# act |
||||
issues = detector._symbolic_call(call, state, address, statespace) |
||||
|
||||
# assert |
||||
issue = issues[0] |
||||
assert issue.address == address |
||||
assert issue.contract == node.contract_name |
||||
assert issue.function == node.function_name |
||||
assert issue.title == "Type: to a user-supplied address" |
||||
assert issue.type == "Informational" |
||||
assert issue.description == ( |
||||
"This contract delegates execution to a contract address obtained from calldata." |
||||
" Be aware that the called contract gets unrestricted access to this contract's state." |
||||
) |
||||
|
||||
|
||||
@patch("mythril.laser.ethereum.state.global_state.GlobalState.get_current_instruction") |
||||
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call") |
||||
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call") |
||||
def test_delegate_call(sym_mock, concrete_mock, curr_instruction): |
||||
# arrange |
||||
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call") |
||||
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call") |
||||
sym_mock.return_value = [] |
||||
concrete_mock.return_value = [] |
||||
curr_instruction.return_value = {"address": "0x10"} |
||||
|
||||
active_account = Account("0x10") |
||||
active_account.code = Disassembly("00") |
||||
|
||||
environment = Environment(active_account, None, None, None, None, None) |
||||
state = GlobalState(None, environment, Node) |
||||
state.mstate.memory = ["placeholder", "calldata_bling_0"] |
||||
state.mstate.stack = [1, 2, 3] |
||||
assert state.get_current_instruction() == {"address": "0x10"} |
||||
|
||||
node = Node("example") |
||||
node.contract_name = "the contract name" |
||||
node.function_name = "fallback" |
||||
|
||||
to = Variable("storage_1", VarType.SYMBOLIC) |
||||
call = Call(node, state, None, "DELEGATECALL", to, None) |
||||
|
||||
statespace = MagicMock() |
||||
statespace.calls = [call] |
||||
|
||||
# act |
||||
detector.execute(statespace) |
||||
|
||||
# assert |
||||
assert concrete_mock.call_count == 1 |
||||
assert sym_mock.call_count == 1 |
||||
|
||||
|
||||
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call") |
||||
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call") |
||||
def test_delegate_call_not_delegate(sym_mock, concrete_mock): |
||||
# arrange |
||||
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call") |
||||
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call") |
||||
sym_mock.return_value = [] |
||||
concrete_mock.return_value = [] |
||||
|
||||
node = Node("example") |
||||
node.function_name = "fallback" |
||||
|
||||
to = Variable("storage_1", VarType.SYMBOLIC) |
||||
call = Call(node, None, None, "NOT_DELEGATECALL", to, None) |
||||
|
||||
statespace = MagicMock() |
||||
statespace.calls = [call] |
||||
|
||||
# act |
||||
issues = detector.execute(statespace) |
||||
|
||||
# assert |
||||
assert issues == [] |
||||
assert concrete_mock.call_count == 0 |
||||
assert sym_mock.call_count == 0 |
||||
|
||||
|
||||
@patch("mythril.analysis.modules.delegatecall.detector._concrete_call") |
||||
@patch("mythril.analysis.modules.delegatecall.detector._symbolic_call") |
||||
def test_delegate_call_not_fallback(sym_mock, concrete_mock): |
||||
# arrange |
||||
# sym_mock = mocker.patch.object(delegatecall, "_symbolic_call") |
||||
# concrete_mock = mocker.patch.object(delegatecall, "_concrete_call") |
||||
sym_mock.return_value = [] |
||||
concrete_mock.return_value = [] |
||||
|
||||
node = Node("example") |
||||
node.function_name = "not_fallback" |
||||
|
||||
to = Variable("storage_1", VarType.SYMBOLIC) |
||||
call = Call(node, None, None, "DELEGATECALL", to, None) |
||||
|
||||
statespace = MagicMock() |
||||
statespace.calls = [call] |
||||
|
||||
# act |
||||
issues = detector.execute(statespace) |
||||
|
||||
# assert |
||||
assert issues == [] |
||||
assert concrete_mock.call_count == 0 |
||||
assert sym_mock.call_count == 0 |
@ -1,41 +1,42 @@ |
||||
import unittest |
||||
from mythril.ether.ethcontract import ETHContract |
||||
from mythril.ethereum.evmcontract import EVMContract |
||||
from tests import BaseTestCase |
||||
|
||||
|
||||
class ETHContractTestCase(unittest.TestCase): |
||||
class EVMContractTestCase(BaseTestCase): |
||||
def setUp(self): |
||||
super().setUp() |
||||
self.code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029" |
||||
self.creation_code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029" |
||||
|
||||
|
||||
class Getinstruction_listTestCase(ETHContractTestCase): |
||||
class Getinstruction_listTestCase(EVMContractTestCase): |
||||
def runTest(self): |
||||
contract = ETHContract(self.code, self.creation_code) |
||||
contract = EVMContract(self.code, self.creation_code) |
||||
|
||||
disassembly = contract.disassembly |
||||
|
||||
self.assertEqual( |
||||
len(disassembly.instruction_list), |
||||
53, |
||||
"Error disassembling code using ETHContract.get_instruction_list()", |
||||
"Error disassembling code using EVMContract.get_instruction_list()", |
||||
) |
||||
|
||||
|
||||
class GetEASMTestCase(ETHContractTestCase): |
||||
class GetEASMTestCase(EVMContractTestCase): |
||||
def runTest(self): |
||||
contract = ETHContract(self.code) |
||||
contract = EVMContract(self.code) |
||||
|
||||
instruction_list = contract.get_easm() |
||||
|
||||
self.assertTrue( |
||||
"PUSH1 0x60" in instruction_list, |
||||
"Error obtaining EASM code through ETHContract.get_easm()", |
||||
"Error obtaining EASM code through EVMContract.get_easm()", |
||||
) |
||||
|
||||
|
||||
class MatchesExpressionTestCase(ETHContractTestCase): |
||||
class MatchesExpressionTestCase(EVMContractTestCase): |
||||
def runTest(self): |
||||
contract = ETHContract(self.code) |
||||
contract = EVMContract(self.code) |
||||
|
||||
self.assertTrue( |
||||
contract.matches_expression("code#PUSH1# or code#PUSH1#"), |
@ -0,0 +1,4 @@ |
||||
[defaults] |
||||
leveldb_dir = /Users/bernhardmueller/Library/Ethereum/geth/chaindata |
||||
dynamic_loading = infura |
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@ |
||||
pragma solidity ^0.4.24; |
||||
pragma solidity 0.5.0; |
||||
|
||||
contract AssertFail { |
||||
|
||||
constructor(uint8 var1){ |
||||
assert(var1>0); |
||||
} |
||||
contract AssertFail { |
||||
constructor(uint8 var1) public { |
||||
assert(var1 > 0); |
||||
} |
||||
} |
||||
|
@ -1,16 +1,19 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract D { |
||||
uint public n; |
||||
address public sender; |
||||
|
||||
function callSetN(address _e, uint _n) { |
||||
_e.call(bytes4(sha3("setN(uint256)")), _n); |
||||
function callSetN(address _e, uint _n) public { |
||||
_e.call(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); |
||||
} |
||||
|
||||
function callcodeSetN(address _e, uint _n) { |
||||
_e.callcode(bytes4(sha3("setN(uint256)")), _n); |
||||
function callcodeSetN(address _e, uint _n) public view { |
||||
_e.staticcall(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); |
||||
} |
||||
|
||||
function delegatecallSetN(address _e, uint _n) { |
||||
_e.delegatecall(bytes4(sha3("setN(uint256)")), _n); |
||||
function delegatecallSetN(address _e, uint _n) public { |
||||
_e.delegatecall(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); |
||||
} |
||||
} |
||||
|
@ -1,17 +1,16 @@ |
||||
pragma solidity ^0.4.17; |
||||
pragma solidity 0.5.0; |
||||
|
||||
contract Transfer1 { |
||||
|
||||
function transfer() { |
||||
msg.sender.transfer(1 ether); |
||||
} |
||||
contract Transfer1 { |
||||
function transfer() public { |
||||
msg.sender.transfer(1 ether); |
||||
} |
||||
|
||||
} |
||||
|
||||
contract Transfer2 { |
||||
|
||||
function transfer() { |
||||
msg.sender.transfer(2 ether); |
||||
} |
||||
|
||||
contract Transfer2 { |
||||
function transfer() public { |
||||
msg.sender.transfer(2 ether); |
||||
} |
||||
} |
||||
|
@ -1,6 +1,8 @@ |
||||
pragma solidity ^0.4.22; |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract nonAscii { |
||||
function renderNonAscii () public pure returns (string) { |
||||
function renderNonAscii () public pure returns (string memory) { |
||||
return "Хэллоу Ворлд"; |
||||
} |
||||
} |
@ -1,20 +1,23 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract Over { |
||||
|
||||
mapping(address => uint) balances; |
||||
uint public totalSupply; |
||||
|
||||
function Token(uint _initialSupply) { |
||||
constructor(uint _initialSupply) public { |
||||
balances[msg.sender] = totalSupply = _initialSupply; |
||||
} |
||||
|
||||
function sendeth(address _to, uint _value) public returns (bool) { |
||||
require(balances[msg.sender] - _value >= 0); |
||||
// require(balances[msg.sender] - _value >= 0); |
||||
balances[msg.sender] -= _value; |
||||
balances[_to] += _value; |
||||
return true; |
||||
} |
||||
|
||||
function balanceOf(address _owner) public constant returns (uint balance) { |
||||
function balanceOf(address _owner) public view returns (uint balance) { |
||||
return balances[_owner]; |
||||
} |
||||
} |
||||
|
@ -1,13 +1,17 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract ReturnValue { |
||||
|
||||
address callee = 0xE0F7e56e62b4267062172495D7506087205A4229; |
||||
address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229; |
||||
|
||||
function callnotchecked() { |
||||
callee.call(); |
||||
function callnotchecked() public { |
||||
callee.call(""); |
||||
} |
||||
|
||||
function callchecked() { |
||||
require(callee.call()); |
||||
function callchecked() public { |
||||
(bool success, bytes memory data) = callee.call(""); |
||||
require(success); |
||||
} |
||||
|
||||
} |
@ -1,152 +1,152 @@ |
||||
contract Rubixi { |
||||
|
||||
//Declare variables for storage critical to contract |
||||
uint private balance = 0; |
||||
uint private collectedFees = 0; |
||||
uint private feePercent = 10; |
||||
uint private pyramidMultiplier = 300; |
||||
uint private payoutOrder = 0; |
||||
|
||||
address private creator; |
||||
|
||||
//Sets creator |
||||
function DynamicPyramid() { |
||||
creator = msg.sender; |
||||
} |
||||
|
||||
modifier onlyowner { |
||||
if (msg.sender == creator) _; |
||||
} |
||||
|
||||
struct Participant { |
||||
address etherAddress; |
||||
uint payout; |
||||
} |
||||
|
||||
Participant[] private participants; |
||||
pragma solidity 0.5.0; |
||||
|
||||
//Fallback function |
||||
function() { |
||||
init(); |
||||
} |
||||
|
||||
//init function run on fallback |
||||
function init() private { |
||||
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid |
||||
if (msg.value < 1 ether) { |
||||
collectedFees += msg.value; |
||||
return; |
||||
} |
||||
|
||||
uint _fee = feePercent; |
||||
//50% fee rebate on any ether value of 50 or greater |
||||
if (msg.value >= 50 ether) _fee /= 2; |
||||
|
||||
addPayout(_fee); |
||||
} |
||||
|
||||
//Function called for valid tx to the contract |
||||
function addPayout(uint _fee) private { |
||||
//Adds new address to participant array |
||||
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100)); |
||||
|
||||
//These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan |
||||
if (participants.length == 10) pyramidMultiplier = 200; |
||||
else if (participants.length == 25) pyramidMultiplier = 150; |
||||
|
||||
// collect fees and update contract balance |
||||
balance += (msg.value * (100 - _fee)) / 100; |
||||
collectedFees += (msg.value * _fee) / 100; |
||||
|
||||
//Pays earlier participiants if balance sufficient |
||||
while (balance > participants[payoutOrder].payout) { |
||||
uint payoutToSend = participants[payoutOrder].payout; |
||||
participants[payoutOrder].etherAddress.send(payoutToSend); |
||||
|
||||
balance -= participants[payoutOrder].payout; |
||||
payoutOrder += 1; |
||||
} |
||||
} |
||||
contract Rubixi { |
||||
//Declare variables for storage critical to contract |
||||
uint private balance = 0; |
||||
uint private collectedFees = 0; |
||||
uint private feePercent = 10; |
||||
uint private pyramidMultiplier = 300; |
||||
uint private payoutOrder = 0; |
||||
|
||||
address payable private creator; |
||||
|
||||
modifier onlyowner { |
||||
if (msg.sender == creator) _; |
||||
} |
||||
|
||||
struct Participant { |
||||
address payable etherAddress; |
||||
uint payout; |
||||
} |
||||
|
||||
//Fallback function |
||||
function() external payable { |
||||
init(); |
||||
} |
||||
|
||||
//Sets creator |
||||
function dynamicPyramid() public { |
||||
creator = msg.sender; |
||||
} |
||||
|
||||
Participant[] private participants; |
||||
|
||||
//Fee functions for creator |
||||
function collectAllFees() public onlyowner { |
||||
require(collectedFees == 0); |
||||
creator.transfer(collectedFees); |
||||
collectedFees = 0; |
||||
} |
||||
|
||||
function collectFeesInEther(uint _amt) public onlyowner { |
||||
_amt *= 1 ether; |
||||
if (_amt > collectedFees) collectAllFees(); |
||||
|
||||
require(collectedFees == 0); |
||||
|
||||
creator.transfer(_amt); |
||||
collectedFees -= _amt; |
||||
} |
||||
|
||||
function collectPercentOfFees(uint _pcent) public onlyowner { |
||||
require(collectedFees == 0 || _pcent > 100); |
||||
|
||||
uint feesToCollect = collectedFees / 100 * _pcent; |
||||
creator.transfer(feesToCollect); |
||||
collectedFees -= feesToCollect; |
||||
} |
||||
|
||||
//Functions for changing variables related to the contract |
||||
function changeOwner(address payable _owner) public onlyowner { |
||||
creator = _owner; |
||||
} |
||||
|
||||
function changeMultiplier(uint _mult) public onlyowner { |
||||
require(_mult > 300 || _mult < 120); |
||||
pyramidMultiplier = _mult; |
||||
} |
||||
|
||||
function changeFeePercentage(uint _fee) public onlyowner { |
||||
require(_fee > 10); |
||||
feePercent = _fee; |
||||
} |
||||
|
||||
//Functions to provide information to end-user using JSON interface or other interfaces |
||||
function currentMultiplier() public view returns (uint multiplier, string memory info) { |
||||
multiplier = pyramidMultiplier; |
||||
info = "This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min."; |
||||
} |
||||
|
||||
function currentFeePercentage() public view returns (uint fee, string memory info) { |
||||
fee = feePercent; |
||||
info = "Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)"; |
||||
} |
||||
|
||||
//Fee functions for creator |
||||
function collectAllFees() onlyowner { |
||||
if (collectedFees == 0) throw; |
||||
function currentPyramidBalanceApproximately() public view returns (uint pyramidBalance, string memory info) { |
||||
pyramidBalance = balance / 1 ether; |
||||
info = "All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to"; |
||||
} |
||||
|
||||
creator.send(collectedFees); |
||||
collectedFees = 0; |
||||
} |
||||
function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) { |
||||
balancePayout = participants[payoutOrder].payout / 1 ether; |
||||
} |
||||
|
||||
function collectFeesInEther(uint _amt) onlyowner { |
||||
_amt *= 1 ether; |
||||
if (_amt > collectedFees) collectAllFees(); |
||||
function feesSeperateFromBalanceApproximately() public view returns (uint fees) { |
||||
fees = collectedFees / 1 ether; |
||||
} |
||||
|
||||
if (collectedFees == 0) throw; |
||||
|
||||
creator.send(_amt); |
||||
collectedFees -= _amt; |
||||
} |
||||
function totalParticipants() public view returns (uint count) { |
||||
count = participants.length; |
||||
} |
||||
|
||||
function collectPercentOfFees(uint _pcent) onlyowner { |
||||
if (collectedFees == 0 || _pcent > 100) throw; |
||||
function numberOfParticipantsWaitingForPayout() public view returns (uint count) { |
||||
count = participants.length - payoutOrder; |
||||
} |
||||
|
||||
uint feesToCollect = collectedFees / 100 * _pcent; |
||||
creator.send(feesToCollect); |
||||
collectedFees -= feesToCollect; |
||||
function participantDetails(uint orderInPyramid) public view returns (address addr, uint payout) { |
||||
if (orderInPyramid <= participants.length) { |
||||
addr = participants[orderInPyramid].etherAddress; |
||||
payout = participants[orderInPyramid].payout / 1 ether; |
||||
} |
||||
} |
||||
|
||||
//Functions for changing variables related to the contract |
||||
function changeOwner(address _owner) onlyowner { |
||||
creator = _owner; |
||||
//init function run on fallback |
||||
function init() private { |
||||
//Ensures only tx with value of 1 ether or greater are processed and added to pyramid |
||||
if (msg.value < 1 ether) { |
||||
collectedFees += msg.value; |
||||
return; |
||||
} |
||||
|
||||
function changeMultiplier(uint _mult) onlyowner { |
||||
if (_mult > 300 || _mult < 120) throw; |
||||
uint _fee = feePercent; |
||||
// 50% fee rebate on any ether value of 50 or greater |
||||
if (msg.value >= 50 ether) _fee /= 2; |
||||
|
||||
pyramidMultiplier = _mult; |
||||
} |
||||
addPayout(_fee); |
||||
} |
||||
|
||||
function changeFeePercentage(uint _fee) onlyowner { |
||||
if (_fee > 10) throw; |
||||
//Function called for valid tx to the contract |
||||
function addPayout(uint _fee) private { |
||||
//Adds new address to participant array |
||||
participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100)); |
||||
|
||||
feePercent = _fee; |
||||
} |
||||
// These statements ensure a quicker payout system to |
||||
// later pyramid entrants, so the pyramid has a longer lifespan |
||||
if (participants.length == 10) pyramidMultiplier = 200; |
||||
else if (participants.length == 25) pyramidMultiplier = 150; |
||||
|
||||
//Functions to provide information to end-user using JSON interface or other interfaces |
||||
function currentMultiplier() constant returns(uint multiplier, string info) { |
||||
multiplier = pyramidMultiplier; |
||||
info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.'; |
||||
} |
||||
|
||||
function currentFeePercentage() constant returns(uint fee, string info) { |
||||
fee = feePercent; |
||||
info = 'Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)'; |
||||
} |
||||
// collect fees and update contract balance |
||||
balance += (msg.value * (100 - _fee)) / 100; |
||||
collectedFees += (msg.value * _fee) / 100; |
||||
|
||||
function currentPyramidBalanceApproximately() constant returns(uint pyramidBalance, string info) { |
||||
pyramidBalance = balance / 1 ether; |
||||
info = 'All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to'; |
||||
} |
||||
|
||||
function nextPayoutWhenPyramidBalanceTotalsApproximately() constant returns(uint balancePayout) { |
||||
balancePayout = participants[payoutOrder].payout / 1 ether; |
||||
} |
||||
|
||||
function feesSeperateFromBalanceApproximately() constant returns(uint fees) { |
||||
fees = collectedFees / 1 ether; |
||||
} |
||||
|
||||
function totalParticipants() constant returns(uint count) { |
||||
count = participants.length; |
||||
} |
||||
|
||||
function numberOfParticipantsWaitingForPayout() constant returns(uint count) { |
||||
count = participants.length - payoutOrder; |
||||
} |
||||
//Pays earlier participiants if balance sufficient |
||||
while (balance > participants[payoutOrder].payout) { |
||||
uint payoutToSend = participants[payoutOrder].payout; |
||||
participants[payoutOrder].etherAddress.transfer(payoutToSend); |
||||
|
||||
function participantDetails(uint orderInPyramid) constant returns(address Address, uint Payout) { |
||||
if (orderInPyramid <= participants.length) { |
||||
Address = participants[orderInPyramid].etherAddress; |
||||
Payout = participants[orderInPyramid].payout / 1 ether; |
||||
} |
||||
balance -= participants[payoutOrder].payout; |
||||
payoutOrder += 1; |
||||
} |
||||
} |
||||
} |
||||
|
@ -1,6 +1,9 @@ |
||||
pragma solidity 0.5.0; |
||||
|
||||
|
||||
contract Suicide { |
||||
|
||||
function kill(address addr) { |
||||
function kill(address payable addr) public { |
||||
selfdestruct(addr); |
||||
} |
||||
|
||||
|
@ -1,126 +1 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 661, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "thisisfine()", |
||||
"swc-id": "107", |
||||
"min_gas_used": 643, |
||||
"max_gas_used": 1254, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 666, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "thisisfine()", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1352, |
||||
"max_gas_used": 35963, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `setstoredaddress(address)`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "callstoredaddress()", |
||||
"swc-id": "107", |
||||
"min_gas_used": 687, |
||||
"max_gas_used": 1298, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 779, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Possible transaction order dependence vulnerability: The value or direction of the call statement is determined from a tainted storage location.", |
||||
"function": "callstoredaddress()", |
||||
"swc-id": "114", |
||||
"min_gas_used": 687, |
||||
"max_gas_used": 1298, |
||||
"title": "Transaction order dependence", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 784, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "callstoredaddress()", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1396, |
||||
"max_gas_used": 36007, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 858, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "107", |
||||
"min_gas_used": 709, |
||||
"max_gas_used": 1320, |
||||
"title": "Message call to external contract", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 869, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "107", |
||||
"min_gas_used": 709, |
||||
"max_gas_used": 1320, |
||||
"title": "State change after external call", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 871, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xe11f493e", |
||||
"swc-id": "104", |
||||
"min_gas_used": 6432, |
||||
"max_gas_used": 61043, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 912, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "calluseraddress(address)", |
||||
"swc-id": "107", |
||||
"min_gas_used": 335, |
||||
"max_gas_used": 616, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 918, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "calluseraddress(address)", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1046, |
||||
"max_gas_used": 35327, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
{"error": null, "issues": [{"address": 661, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "thisisfine()", "max_gas_used": 1254, "min_gas_used": 643, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 666, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "thisisfine()", "max_gas_used": 35963, "min_gas_used": 1352, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 779, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "callstoredaddress()", "max_gas_used": 1298, "min_gas_used": 687, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 784, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "callstoredaddress()", "max_gas_used": 36007, "min_gas_used": 1396, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 858, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call to an external address. Verify that the code at this address is trusted and immutable.", "function": "reentrancy()", "max_gas_used": 1320, "min_gas_used": 709, "swc-id": "107", "title": "External call", "type": "Informational"}, {"address": 871, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "reentrancy()", "max_gas_used": 61043, "min_gas_used": 6432, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 912, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "calluseraddress(address)", "max_gas_used": 616, "min_gas_used": 335, "swc-id": "107", "title": "External call to user-supplied address", "type": "Warning"}, {"address": 918, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "calluseraddress(address)", "max_gas_used": 35327, "min_gas_used": 1046, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
@ -1,36 +1,36 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 158, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 278, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 378, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The substraction can result in an integer underflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"success": true |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 158, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning", |
||||
}, |
||||
{ |
||||
"address": 278, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The arithmetic operation can result in integer overflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning", |
||||
}, |
||||
{ |
||||
"address": 378, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The substraction can result in an integer underflow.\n", |
||||
"function": "_function_0x83f12fec", |
||||
"swc-id": "101", |
||||
"title": "Integer Underflow", |
||||
"type": "Warning", |
||||
}, |
||||
], |
||||
"success": true, |
||||
} |
||||
|
@ -1,30 +1,5 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 722, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability.", |
||||
"function": "withdrawfunds()", |
||||
"max_gas_used": 1749, |
||||
"min_gas_used": 1138, |
||||
"swc-id": "105", |
||||
"title": "Ether thief", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 883, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This binary add operation can result in integer overflow.\n", |
||||
"function": "invest()", |
||||
"max_gas_used": 1856, |
||||
"min_gas_used": 1571, |
||||
"swc-id": "101", |
||||
"title": "Integer Overflow", |
||||
"type": "Warning" |
||||
} |
||||
], |
||||
"issues": [], |
||||
"success": true |
||||
} |
||||
|
@ -1,25 +1,3 @@ |
||||
# Analysis results for test-filename.sol |
||||
# Analysis results for None |
||||
|
||||
## Ether thief |
||||
- SWC ID: 105 |
||||
- Type: Warning |
||||
- Contract: Unknown |
||||
- Function name: `withdrawfunds()` |
||||
- PC address: 722 |
||||
- Estimated Gas Usage: 1138 - 1749 |
||||
|
||||
### Description |
||||
|
||||
Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability. |
||||
|
||||
## Integer Overflow |
||||
- SWC ID: 101 |
||||
- Type: Warning |
||||
- Contract: Unknown |
||||
- Function name: `invest()` |
||||
- PC address: 883 |
||||
- Estimated Gas Usage: 1571 - 1856 |
||||
|
||||
### Description |
||||
|
||||
This binary add operation can result in integer overflow. |
||||
The analysis was completed successfully. No issues were detected. |
||||
|
@ -1,21 +1 @@ |
||||
==== Ether thief ==== |
||||
SWC ID: 105 |
||||
Type: Warning |
||||
Contract: Unknown |
||||
Function name: withdrawfunds() |
||||
PC address: 722 |
||||
Estimated Gas Usage: 1138 - 1749 |
||||
Arbitrary senders other than the contract creator can withdraw ETH from the contract account without previously having sent an equivalent amount of ETH to it. This is likely to be a vulnerability. |
||||
-------------------- |
||||
|
||||
==== Integer Overflow ==== |
||||
SWC ID: 101 |
||||
Type: Warning |
||||
Contract: Unknown |
||||
Function name: invest() |
||||
PC address: 883 |
||||
Estimated Gas Usage: 1571 - 1856 |
||||
This binary add operation can result in integer overflow. |
||||
|
||||
-------------------- |
||||
|
||||
The analysis was completed successfully. No issues were detected. |
||||
|
@ -1,54 +1 @@ |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 626, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x141f32ff", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1104, |
||||
"max_gas_used": 35856, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 857, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x9b58bc26", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1167, |
||||
"max_gas_used": 35919, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 1038, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", |
||||
"function": "_function_0xeea4c864", |
||||
"swc-id": "107", |
||||
"min_gas_used": 477, |
||||
"max_gas_used": 1229, |
||||
"title": "Message call to external contract", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 1046, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xeea4c864", |
||||
"swc-id": "104", |
||||
"min_gas_used": 1192, |
||||
"max_gas_used": 35944, |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
{"error": null, "issues": [{"address": 626, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "max_gas_used": 35856, "min_gas_used": 1104, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "max_gas_used": 35919, "min_gas_used": 1167, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "_function_0xeea4c864", "max_gas_used": 1229, "min_gas_used": 477, "swc-id": "107", "title": "External call to user-supplied address", "type": "Warning"}, {"address": 1046, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "max_gas_used": 35944, "min_gas_used": 1192, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue