From 622a1d63e6bf06624076f8b0c1745910fd8641ae Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sat, 24 Nov 2018 19:38:42 +0100 Subject: [PATCH 01/14] Fix native tests --- tests/native_test.py | 60 ++++--------- tests/native_tests.sol | 196 +++++++++++++++-------------------------- 2 files changed, 88 insertions(+), 168 deletions(-) diff --git a/tests/native_test.py b/tests/native_test.py index 01eda4a8..86f629a7 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -5,48 +5,26 @@ from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum import svm from tests import * +SHA256_TEST = [(0, False) for _ in range(4)] +RIPEMD160_TEST = [(0, False) for _ in range(2)] +ECRECOVER_TEST = [(0, False) for _ in range(2)] +IDENTITY_TEST = [(0, False) for _ in range(2)] -SHA256_TEST = [(0, False) for _ in range(6)] +# These are Random numbers to check whether the 'if condition' is entered or not +# (True means entered) +SHA256_TEST[0] = (hex(5555555555555555), True) +SHA256_TEST[1] = (hex(323232325445454546), True) +SHA256_TEST[2] = (hex(34756834765834658), True) +SHA256_TEST[3] = (hex(8756476956956795876987), True) -RIPEMD160_TEST = [(0, False) for _ in range(6)] +RIPEMD160_TEST[0] = (hex(999999999999999999993), True) +RIPEMD160_TEST[1] = (hex(1111111111112), True) -ECRECOVER_TEST = [(0, False) for _ in range(9)] +ECRECOVER_TEST[0] = (hex(674837568743979857398564869), True) +ECRECOVER_TEST[1] = (hex(3487683476979311), False) -IDENTITY_TEST = [(0, False) for _ in range(4)] - -SHA256_TEST[0] = ( - 5555555555555555, - True, -) # These are Random numbers to check whether the 'if condition' is entered or not(True means entered) -SHA256_TEST[1] = (323232325445454546, True) -SHA256_TEST[2] = (34756834765834658, False) -SHA256_TEST[3] = (8756476956956795876987, True) -SHA256_TEST[4] = (5763467587689578369, True) -SHA256_TEST[5] = (948365957658767467857, False) - -RIPEMD160_TEST[0] = (1242435356364, True) -RIPEMD160_TEST[1] = (6732648654386435, True) -RIPEMD160_TEST[2] = (97457657536546465, False) -RIPEMD160_TEST[3] = (56436346436456546, True) -RIPEMD160_TEST[4] = (999999999999999999993, True) -RIPEMD160_TEST[5] = (1111111111112, False) - - -ECRECOVER_TEST[0] = (786428768768632537676, True) -ECRECOVER_TEST[1] = (4897983476979346779638, False) -ECRECOVER_TEST[2] = (674837568743979857398564869, True) -ECRECOVER_TEST[3] = (3487683476979311, False) -ECRECOVER_TEST[4] = (853729594875984769847369, True) -ECRECOVER_TEST[5] = (83579382475972439587, False) -ECRECOVER_TEST[6] = (8437589437695876985769, True) -ECRECOVER_TEST[7] = (9486794873598347697596, False) -ECRECOVER_TEST[8] = (346934876983476, True) - -IDENTITY_TEST[0] = (87426857369875698, True) -IDENTITY_TEST[1] = (476934798798347, False) - -IDENTITY_TEST[2] = (7346948379483769, True) -IDENTITY_TEST[3] = (83269476937987, False) +IDENTITY_TEST[0] = (hex(87426857369875698), True) +IDENTITY_TEST[1] = (hex(476934798798347), False) def _all_info(laser): @@ -98,10 +76,10 @@ def _all_info(laser): def _test_natives(laser_info, test_list, test_name): success = 0 for i, j in test_list: - if (str(i) in laser_info) == j: + if (str(i) in laser_info or str(int(i, 16)) in laser_info) == j: success += 1 else: - print("Failed: " + str(i) + " " + str(j)) + print("Failed:", str(int(i, 16)), str(j)) assert success == len(test_list) @@ -116,8 +94,8 @@ class NativeTests(BaseTestCase): laser.sym_exec(account.address) laser_info = str(_all_info(laser)) - print("\n") + print(laser_info) _test_natives(laser_info, SHA256_TEST, "SHA256") _test_natives(laser_info, RIPEMD160_TEST, "RIPEMD160") _test_natives(laser_info, ECRECOVER_TEST, "ECRECOVER") diff --git a/tests/native_tests.sol b/tests/native_tests.sol index 762d8443..f321e38c 100644 --- a/tests/native_tests.sol +++ b/tests/native_tests.sol @@ -1,147 +1,90 @@ -pragma solidity ^0.4.17; +pragma solidity 0.5.0; contract Caller { - address public fixed_address; //Just some useless variables - address public stored_address; + //Just some useless variables + address public fixedAddress; + address public storedAddress; - uint256 statevar; //useless( but good for testing as they contribute as decoys) - bytes32 far; + //useless (but good for testing as they contribute as decoys) + uint256 private statevar; + bytes32 private far; - function Caller(address addr) { - fixed_address = addr; + constructor (address addr) public { + fixedAddress = addr; } - function thisisfine() public { //some typical function as a decoy - fixed_address.call(); + //some typical function as a decoy + function thisisfine() public { + (bool success, bytes memory mem) = fixedAddress.call(""); } - function sha256_test1() public { + + function sha256Test1() public returns (uint256) { uint256 i; - if(sha256('ab','c') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True + if (sha256(abi.encodePacked("ab", "c")) == sha256("abc")) { + // True i = 5555555555555555; - } - - if(sha256('abc') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True + } else { + // False i = 323232325445454546; } + return i; } - function sha256_test2() public { + + function sha256Test2() public returns (uint256) { uint256 i; - if(sha256('abd') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad) { //False + if (sha256("abd") == sha256(abi.encodePacked("ab", "d"))) { + // True i = 34756834765834658; - } - if(sha256('ab','d') == 0xa52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9) { //True + } else { + // False i = 8756476956956795876987; } - } - function sha256_test3() public { - uint256 i; - if(sha256('') == 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855) { //True - i = 5763467587689578369; - } - if(sha256('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdhhfdhhhhhh') == 0xe4ebd771f821e3277b77dcc39e94fe7172a5c9c8c12f8885c2d5513385a0a8b8) { //False - i = 948365957658767467857; - } + return i; } - function ripemd_test1() public { - uint256 i; - if(ripemd160('ab','c') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True - i = 1242435356364; - } - if(ripemd160('abc') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True - i = 6732648654386435; - } - } - function ripemd_test2() public { - uint256 i; - if(ripemd160('abd') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc) { //False - i = 97457657536546465; - } - if(ripemd160('ab','d') == 0xb0a79cc77e333ea11974e105cd051d33836928b0) { //True - i = 56436346436456546; - } - } - function ripemd_test3() public { - uint256 i; - if(ripemd160('') == 0x9c1185a5c5e9fc54612808977ee8f548b2258d31) { //True - i = 999999999999999999993; - } - if(ripemd160('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh') == 0x2d1b88a5daa5d138eb7bb14ee320010937f0ebe7) { //False - i = 1111111111112; - } - } + function ripemdTest() public returns (uint256) { + uint256 i; + bytes20 v1 = ripemd160(""); + bytes20 v2 = ripemd160("hhhhh"); - function ecrecover_test1() public { - bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - bytes32 prefixedHash = keccak256(prefix, foobar); + if (v1 != v2) { + // True + i = 999999999999999999993; + } else { + // False + i = 1111111111112; + } + return i; + } + + function ecrecoverTest() public returns (uint256) { + bytes32 foobar1 = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; + bytes32 foobar2 = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; uint8 v = 28; bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; - if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8a) { //True - uint256 bignum = 786428768768632537676; - } - if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False - uint256 small = 4897983476979346779638; - } - foobar = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; - if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //True - uint256 dk = 674837568743979857398564869; - } - foobar = 0x38d18acb67d25c7bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; //not same as above, minor change(7bb instead of 8bb) - if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //False - uint256 pk = 3487683476979311; + uint256 i; + address addr1 = ecrecover(keccak256(abi.encodePacked(foobar1)), v, r, s); + address addr2 = ecrecover(keccak256(abi.encodePacked(foobar1, foobar2)), v, r, s); + if (addr1 != addr2) { + // True + i = 674837568743979857398564869; + } else { + // False + i = 3487683476979311; } - + return i; } - function ecrecover_test2() public { - bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - bytes32 prefixedHash = keccak256(prefix, foobar); - uint8 v = 26; - bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; - bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; - if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True - uint256 bignum = 853729594875984769847369; - } - if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False - uint256 small = 83579382475972439587; - } - } - function ecrecover_test3() public { - bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - bytes32 prefixedHash = keccak256(prefix, foobar); - uint8 v = 29; - bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; - bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; - if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True - uint256 bignum = 8437589437695876985769; - } - if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False - uint256 small = 9486794873598347697596; - } + //identity is invoked here in compiler and not below + function needIdentityInvoke(uint sea) public returns (uint) { + return sea; } - function ecrecover_test4() public { - bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; - bytes memory prefix = "\x19Ethereum Signed Message:\n32"; - bytes32 prefixedHash = keccak256(prefix, foobar); - uint8 v = 27; - bytes32 r = 0xfffffffffffffffffffffffffffffffffaaedce6af48a03bbfd25e8cd0364141; //greater than the max limit - bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; - if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True - uint256 bignum = 346934876983476; - } - } - function need_identity_invoke(uint sea) returns (uint) { - return sea; //identity is invoked here in compiler and not below - } - function identity_function(int input) public returns(int out) { - assembly{ + function identityFunction(int input) public returns(int out) { + assembly { let x := mload(0x40) mstore(x, input) @@ -150,17 +93,16 @@ contract Caller { mstore(0x40, x) } } - function identity_test1() public{ - if(identity_function(100)==100) //True - uint256 smallnum = 87426857369875698; - if(identity_function(200)==100) //False - uint256 bignum = 476934798798347; - } - function identity_test2() public{ - if(identity_function(12345678)==12345678) //True - uint256 smallnum = 7346948379483769; - if(identity_function(74648796976)==4685987) //False - uint256 bignum = 83269476937987; - } + function identityTest1() public returns (uint256) { + uint256 i; + if (identityFunction(100) == 100) { + // True + i = 87426857369875698; + } else { + // False + i = 476934798798347; + } + return i; + } } From 9787a4a666c76b98e4a0d0e9d1f8c2c0328d66c1 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sat, 24 Nov 2018 19:38:55 +0100 Subject: [PATCH 02/14] Fix multi contracts --- .../input_contracts/multi_contracts.sol | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/testdata/input_contracts/multi_contracts.sol b/tests/testdata/input_contracts/multi_contracts.sol index e4a4464a..c8c4e76a 100644 --- a/tests/testdata/input_contracts/multi_contracts.sol +++ b/tests/testdata/input_contracts/multi_contracts.sol @@ -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); + } } From e11e916f55e53f127ff5a07755a7096c7de211e6 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sat, 24 Nov 2018 19:40:32 +0100 Subject: [PATCH 03/14] Fix constructor assert --- tests/testdata/input_contracts/constructor_assert.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/testdata/input_contracts/constructor_assert.sol b/tests/testdata/input_contracts/constructor_assert.sol index aff01b47..fa1e7018 100644 --- a/tests/testdata/input_contracts/constructor_assert.sol +++ b/tests/testdata/input_contracts/constructor_assert.sol @@ -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); + } } From a053cfd330d2bf6f54000a070947581dff6308aa Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sat, 24 Nov 2018 20:19:47 +0100 Subject: [PATCH 04/14] Fix rubixi --- tests/testdata/input_contracts/rubixi.sol | 264 +++++++++++----------- 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/tests/testdata/input_contracts/rubixi.sol b/tests/testdata/input_contracts/rubixi.sol index 91fda1b6..c8aa2c77 100644 --- a/tests/testdata/input_contracts/rubixi.sol +++ b/tests/testdata/input_contracts/rubixi.sol @@ -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 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 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 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 returns (uint balancePayout) { + balancePayout = participants[payoutOrder].payout / 1 ether; + } - function collectFeesInEther(uint _amt) onlyowner { - _amt *= 1 ether; - if (_amt > collectedFees) collectAllFees(); + function feesSeperateFromBalanceApproximately() public returns (uint fees) { + fees = collectedFees / 1 ether; + } - if (collectedFees == 0) throw; - - creator.send(_amt); - collectedFees -= _amt; - } + function totalParticipants() public returns (uint count) { + count = participants.length; + } - function collectPercentOfFees(uint _pcent) onlyowner { - if (collectedFees == 0 || _pcent > 100) throw; + function numberOfParticipantsWaitingForPayout() public returns (uint count) { + count = participants.length - payoutOrder; + } - uint feesToCollect = collectedFees / 100 * _pcent; - creator.send(feesToCollect); - collectedFees -= feesToCollect; + function participantDetails(uint orderInPyramid) public 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; } + } } From e47584f02d4bf440e70169374d5daf72987b3c97 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sat, 24 Nov 2018 20:28:58 +0100 Subject: [PATCH 05/14] Fix other contracts --- tests/testdata/input_contracts/calls.sol | 28 +++++++++---------- .../testdata/input_contracts/environments.sol | 2 +- tests/testdata/input_contracts/ether_send.sol | 3 ++ tests/testdata/input_contracts/exceptions.sol | 5 +++- .../input_contracts/kinds_of_calls.sol | 3 ++ tests/testdata/input_contracts/metacoin.sol | 5 ++-- tests/testdata/input_contracts/nonascii.sol | 4 ++- tests/testdata/input_contracts/origin.sol | 9 ++++-- tests/testdata/input_contracts/overflow.sol | 3 ++ .../testdata/input_contracts/returnvalue.sol | 3 ++ tests/testdata/input_contracts/suicide.sol | 3 ++ tests/testdata/input_contracts/underflow.sol | 3 ++ .../testdata/input_contracts/weak_random.sol | 3 +- 13 files changed, 51 insertions(+), 23 deletions(-) diff --git a/tests/testdata/input_contracts/calls.sol b/tests/testdata/input_contracts/calls.sol index a9069782..513e31fb 100644 --- a/tests/testdata/input_contracts/calls.sol +++ b/tests/testdata/input_contracts/calls.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.17; +pragma solidity 0.5.0; contract Caller { @@ -8,29 +8,29 @@ contract Caller { uint256 statevar; - function Caller(address addr) { + constructor(address addr) public { fixed_address = addr; } function thisisfine() public { - fixed_address.call(); + fixed_address.call(""); } function reentrancy() public { - fixed_address.call(); + fixed_address.call(""); statevar = 0; } - - function calluseraddress(address addr) { - addr.call(); + + function calluseraddress(address addr) public { + addr.call(""); + } + + function callstoredaddress() public { + stored_address.call(""); } - function callstoredaddress() { - stored_address.call(); - } - - function setstoredaddress(address addr) { + function setstoredaddress(address addr) public { stored_address = addr; - } - + } + } \ No newline at end of file diff --git a/tests/testdata/input_contracts/environments.sol b/tests/testdata/input_contracts/environments.sol index d79b63f3..156f0cbe 100644 --- a/tests/testdata/input_contracts/environments.sol +++ b/tests/testdata/input_contracts/environments.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.16; +pragma solidity 0.5.0; contract IntegerOverflow2 { diff --git a/tests/testdata/input_contracts/ether_send.sol b/tests/testdata/input_contracts/ether_send.sol index a814332b..e36f57ee 100644 --- a/tests/testdata/input_contracts/ether_send.sol +++ b/tests/testdata/input_contracts/ether_send.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract Crowdfunding { mapping(address => uint) public balances; diff --git a/tests/testdata/input_contracts/exceptions.sol b/tests/testdata/input_contracts/exceptions.sol index 95c42da0..d489bf02 100644 --- a/tests/testdata/input_contracts/exceptions.sol +++ b/tests/testdata/input_contracts/exceptions.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract Exceptions { uint256[8] myarray; @@ -28,7 +31,7 @@ contract Exceptions { if (input > 0) { uint256 i = 1/input; } - } + } function arrayaccess(uint256 index) { uint256 i = myarray[index]; diff --git a/tests/testdata/input_contracts/kinds_of_calls.sol b/tests/testdata/input_contracts/kinds_of_calls.sol index 80bedee6..c60ddc70 100644 --- a/tests/testdata/input_contracts/kinds_of_calls.sol +++ b/tests/testdata/input_contracts/kinds_of_calls.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract D { uint public n; address public sender; diff --git a/tests/testdata/input_contracts/metacoin.sol b/tests/testdata/input_contracts/metacoin.sol index 8627c1d9..961a1f67 100644 --- a/tests/testdata/input_contracts/metacoin.sol +++ b/tests/testdata/input_contracts/metacoin.sol @@ -1,11 +1,12 @@ -pragma solidity ^0.4.17; +pragma solidity 0.5.0; + contract MetaCoin { mapping (address => uint) public balances; function MetaCoin() public { balances[msg.sender] = 10000; } - + function sendToken(address receiver, uint amount) public returns(bool successful){ if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; diff --git a/tests/testdata/input_contracts/nonascii.sol b/tests/testdata/input_contracts/nonascii.sol index 73ccbe62..6cb5a1f2 100644 --- a/tests/testdata/input_contracts/nonascii.sol +++ b/tests/testdata/input_contracts/nonascii.sol @@ -1,4 +1,6 @@ -pragma solidity ^0.4.22; +pragma solidity 0.5.0; + + contract nonAscii { function renderNonAscii () public pure returns (string) { return "Хэллоу Ворлд"; diff --git a/tests/testdata/input_contracts/origin.sol b/tests/testdata/input_contracts/origin.sol index 635c15f4..32df0ad0 100644 --- a/tests/testdata/input_contracts/origin.sol +++ b/tests/testdata/input_contracts/origin.sol @@ -1,8 +1,11 @@ +pragma solidity 0.5.0; + + contract Origin { address public owner; - /** + /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ @@ -12,7 +15,7 @@ contract Origin { /** - * @dev Throws if called by any account other than the owner. + * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { if (tx.origin != owner) { @@ -24,7 +27,7 @@ contract Origin { /** * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. + * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) onlyOwner { if (newOwner != address(0)) { diff --git a/tests/testdata/input_contracts/overflow.sol b/tests/testdata/input_contracts/overflow.sol index f61a8b0e..5c4f8e28 100644 --- a/tests/testdata/input_contracts/overflow.sol +++ b/tests/testdata/input_contracts/overflow.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract Over { mapping(address => uint) balances; diff --git a/tests/testdata/input_contracts/returnvalue.sol b/tests/testdata/input_contracts/returnvalue.sol index 819580f3..3918731d 100644 --- a/tests/testdata/input_contracts/returnvalue.sol +++ b/tests/testdata/input_contracts/returnvalue.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract ReturnValue { address callee = 0xE0F7e56e62b4267062172495D7506087205A4229; diff --git a/tests/testdata/input_contracts/suicide.sol b/tests/testdata/input_contracts/suicide.sol index 1763365b..93fe7401 100644 --- a/tests/testdata/input_contracts/suicide.sol +++ b/tests/testdata/input_contracts/suicide.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract Suicide { function kill(address addr) { diff --git a/tests/testdata/input_contracts/underflow.sol b/tests/testdata/input_contracts/underflow.sol index 6ecef5df..a3480d7f 100644 --- a/tests/testdata/input_contracts/underflow.sol +++ b/tests/testdata/input_contracts/underflow.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract Under { mapping(address => uint) balances; diff --git a/tests/testdata/input_contracts/weak_random.sol b/tests/testdata/input_contracts/weak_random.sol index 88fc4e12..8833c875 100644 --- a/tests/testdata/input_contracts/weak_random.sol +++ b/tests/testdata/input_contracts/weak_random.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.4.16; +pragma solidity 0.5.0; + contract WeakRandom { struct Contestant { From 4c3eeb2a77df32074e847a9636b447cae65507b5 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sun, 25 Nov 2018 14:00:29 +0100 Subject: [PATCH 06/14] Port other test contracts to solc 0.5.0 --- tests/testdata/input_contracts/environments.sol | 2 +- tests/testdata/input_contracts/ether_send.sol | 8 ++++---- tests/testdata/input_contracts/exceptions.sol | 16 ++++++++-------- .../testdata/input_contracts/kinds_of_calls.sol | 12 ++++++------ tests/testdata/input_contracts/metacoin.sol | 2 +- tests/testdata/input_contracts/nonascii.sol | 2 +- tests/testdata/input_contracts/origin.sol | 8 +++----- tests/testdata/input_contracts/overflow.sol | 4 ++-- tests/testdata/input_contracts/returnvalue.sol | 11 ++++++----- tests/testdata/input_contracts/suicide.sol | 2 +- tests/testdata/input_contracts/underflow.sol | 4 ++-- tests/testdata/input_contracts/weak_random.sol | 14 +++++++------- 12 files changed, 42 insertions(+), 43 deletions(-) diff --git a/tests/testdata/input_contracts/environments.sol b/tests/testdata/input_contracts/environments.sol index 156f0cbe..4a3a66a4 100644 --- a/tests/testdata/input_contracts/environments.sol +++ b/tests/testdata/input_contracts/environments.sol @@ -5,7 +5,7 @@ contract IntegerOverflow2 { uint256 public count = 7; mapping(address => uint256) balances; - function batchTransfer(address[] _receivers, uint256 _value) public returns(bool){ + function batchTransfer(address[] memory _receivers, uint256 _value) public returns(bool){ uint cnt = _receivers.length; uint256 amount = uint256(cnt) * _value; diff --git a/tests/testdata/input_contracts/ether_send.sol b/tests/testdata/input_contracts/ether_send.sol index e36f57ee..23f20ff6 100644 --- a/tests/testdata/input_contracts/ether_send.sol +++ b/tests/testdata/input_contracts/ether_send.sol @@ -13,12 +13,12 @@ contract Crowdfunding { _; } - function crowdfunding() { + function crowdfunding() public { owner = msg.sender; } - function withdrawfunds() onlyOwner { - msg.sender.transfer(this.balance); + function withdrawfunds() public onlyOwner { + msg.sender.transfer(address(this).balance); } function invest() public payable { @@ -27,7 +27,7 @@ contract Crowdfunding { balances[msg.sender] += msg.value; } - function getBalance() public constant returns (uint) { + function getBalance() public returns (uint) { return balances[msg.sender]; } diff --git a/tests/testdata/input_contracts/exceptions.sol b/tests/testdata/input_contracts/exceptions.sol index d489bf02..6e2632f6 100644 --- a/tests/testdata/input_contracts/exceptions.sol +++ b/tests/testdata/input_contracts/exceptions.sol @@ -5,39 +5,39 @@ contract Exceptions { uint256[8] myarray; - function assert1() { + function assert1() public { uint256 i = 1; assert(i == 0); } - function assert2() { + function assert2() public { uint256 i = 1; assert(i > 0); } - function assert3(uint256 input) { + function assert3(uint256 input) public { assert(input != 23); } - function requireisfine(uint256 input) { + function requireisfine(uint256 input) public { require(input != 23); } - function divisionby0(uint256 input) { + function divisionby0(uint256 input) public { uint256 i = 1/input; } - function thisisfine(uint256 input) { + function thisisfine(uint256 input) public { if (input > 0) { uint256 i = 1/input; } } - function arrayaccess(uint256 index) { + function arrayaccess(uint256 index) public { uint256 i = myarray[index]; } - function thisisalsofind(uint256 index) { + function thisisalsofind(uint256 index) public { if (index < 8) { uint256 i = myarray[index]; } diff --git a/tests/testdata/input_contracts/kinds_of_calls.sol b/tests/testdata/input_contracts/kinds_of_calls.sol index c60ddc70..10cec2cd 100644 --- a/tests/testdata/input_contracts/kinds_of_calls.sol +++ b/tests/testdata/input_contracts/kinds_of_calls.sol @@ -5,15 +5,15 @@ 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 { + _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)); } } diff --git a/tests/testdata/input_contracts/metacoin.sol b/tests/testdata/input_contracts/metacoin.sol index 961a1f67..557c0d11 100644 --- a/tests/testdata/input_contracts/metacoin.sol +++ b/tests/testdata/input_contracts/metacoin.sol @@ -3,7 +3,7 @@ pragma solidity 0.5.0; contract MetaCoin { mapping (address => uint) public balances; - function MetaCoin() public { + constructor() public { balances[msg.sender] = 10000; } diff --git a/tests/testdata/input_contracts/nonascii.sol b/tests/testdata/input_contracts/nonascii.sol index 6cb5a1f2..d8a28a61 100644 --- a/tests/testdata/input_contracts/nonascii.sol +++ b/tests/testdata/input_contracts/nonascii.sol @@ -2,7 +2,7 @@ pragma solidity 0.5.0; contract nonAscii { - function renderNonAscii () public pure returns (string) { + function renderNonAscii () public pure returns (string memory) { return "Хэллоу Ворлд"; } } \ No newline at end of file diff --git a/tests/testdata/input_contracts/origin.sol b/tests/testdata/input_contracts/origin.sol index 32df0ad0..2ceb10f8 100644 --- a/tests/testdata/input_contracts/origin.sol +++ b/tests/testdata/input_contracts/origin.sol @@ -9,7 +9,7 @@ contract Origin { * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - function Origin() { + constructor() public { owner = msg.sender; } @@ -18,9 +18,7 @@ contract Origin { * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { - if (tx.origin != owner) { - throw; - } + require(tx.origin != owner); _; } @@ -29,7 +27,7 @@ contract Origin { * @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 { + function transferOwnership(address newOwner) public onlyOwner { if (newOwner != address(0)) { owner = newOwner; } diff --git a/tests/testdata/input_contracts/overflow.sol b/tests/testdata/input_contracts/overflow.sol index 5c4f8e28..52d0c9d9 100644 --- a/tests/testdata/input_contracts/overflow.sol +++ b/tests/testdata/input_contracts/overflow.sol @@ -6,7 +6,7 @@ contract Over { mapping(address => uint) balances; uint public totalSupply; - function Token(uint _initialSupply) { + constructor(uint _initialSupply) public { balances[msg.sender] = totalSupply = _initialSupply; } @@ -17,7 +17,7 @@ contract Over { return true; } - function balanceOf(address _owner) public constant returns (uint balance) { + function balanceOf(address _owner) public returns (uint balance) { return balances[_owner]; } } diff --git a/tests/testdata/input_contracts/returnvalue.sol b/tests/testdata/input_contracts/returnvalue.sol index 3918731d..88bd8805 100644 --- a/tests/testdata/input_contracts/returnvalue.sol +++ b/tests/testdata/input_contracts/returnvalue.sol @@ -3,14 +3,15 @@ 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); } } \ No newline at end of file diff --git a/tests/testdata/input_contracts/suicide.sol b/tests/testdata/input_contracts/suicide.sol index 93fe7401..9e25678c 100644 --- a/tests/testdata/input_contracts/suicide.sol +++ b/tests/testdata/input_contracts/suicide.sol @@ -3,7 +3,7 @@ pragma solidity 0.5.0; contract Suicide { - function kill(address addr) { + function kill(address payable addr) public { selfdestruct(addr); } diff --git a/tests/testdata/input_contracts/underflow.sol b/tests/testdata/input_contracts/underflow.sol index a3480d7f..c1f872f5 100644 --- a/tests/testdata/input_contracts/underflow.sol +++ b/tests/testdata/input_contracts/underflow.sol @@ -6,7 +6,7 @@ contract Under { mapping(address => uint) balances; uint public totalSupply; - function Token(uint _initialSupply) { + constructor(uint _initialSupply) public { balances[msg.sender] = totalSupply = _initialSupply; } @@ -17,7 +17,7 @@ contract Under { return true; } - function balanceOf(address _owner) public constant returns (uint balance) { + function balanceOf(address _owner) public returns (uint balance) { return balances[_owner]; } } \ No newline at end of file diff --git a/tests/testdata/input_contracts/weak_random.sol b/tests/testdata/input_contracts/weak_random.sol index 8833c875..5acdd7ef 100644 --- a/tests/testdata/input_contracts/weak_random.sol +++ b/tests/testdata/input_contracts/weak_random.sol @@ -3,19 +3,19 @@ pragma solidity 0.5.0; contract WeakRandom { struct Contestant { - address addr; + address payable addr; uint gameId; } - uint public constant prize = 2.5 ether; - uint public constant totalTickets = 50; - uint public constant pricePerTicket = prize / totalTickets; + uint public prize = 2.5 ether; + uint public totalTickets = 50; + uint public pricePerTicket = prize / totalTickets; uint public gameId = 1; uint public nextTicket = 0; mapping (uint => Contestant) public contestants; - function () payable public { + function () payable external { uint moneySent = msg.value; while (moneySent >= pricePerTicket && nextTicket < totalTickets) { @@ -38,10 +38,10 @@ contract WeakRandom { address seed1 = contestants[uint(block.coinbase) % totalTickets].addr; address seed2 = contestants[uint(msg.sender) % totalTickets].addr; uint seed3 = block.difficulty; - bytes32 randHash = keccak256(seed1, seed2, seed3); + bytes32 randHash = keccak256(abi.encode(seed1, seed2, seed3)); uint winningNumber = uint(randHash) % totalTickets; - address winningAddress = contestants[winningNumber].addr; + address payable winningAddress = contestants[winningNumber].addr; gameId++; nextTicket = 0; From 8813792e36ee139a16fddb281b0914454db27397 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sun, 25 Nov 2018 14:20:59 +0100 Subject: [PATCH 07/14] Fix solidity contract test --- tests/solidity_contract_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/solidity_contract_test.py b/tests/solidity_contract_test.py index dd7cc3fb..916b68cd 100644 --- a/tests/solidity_contract_test.py +++ b/tests/solidity_contract_test.py @@ -31,8 +31,8 @@ class SolidityContractTest(BaseTestCase): input_file = TEST_FILES / "constructor_assert.sol" contract = SolidityContract(str(input_file), name="AssertFail") - code_info = contract.get_source_info(62, constructor=True) + code_info = contract.get_source_info(70, constructor=True) self.assertEqual(code_info.filename, str(input_file)) self.assertEqual(code_info.lineno, 6) - self.assertEqual(code_info.code, "assert(var1>0)") + self.assertEqual(code_info.code, "assert(var1 > 0)") From e94aee1c8289d20d5023a7c36b286960a2011a04 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Sun, 25 Nov 2018 17:01:50 +0100 Subject: [PATCH 08/14] Port example contracts to solc 0.5.0 --- solidity_examples/BECToken.sol | 42 ++--- solidity_examples/WalletLibrary.sol | 104 +++++------ solidity_examples/calls.sol | 28 +-- solidity_examples/etherstore.sol | 6 +- solidity_examples/exceptions.sol | 21 ++- solidity_examples/hashforether.sol | 11 +- solidity_examples/origin.sol | 17 +- solidity_examples/returnvalue.sol | 14 +- solidity_examples/rubixi.sol | 264 ++++++++++++++-------------- solidity_examples/suicide.sol | 5 +- solidity_examples/timelock.sol | 3 + solidity_examples/token.sol | 7 +- solidity_examples/weak_random.sol | 17 +- 13 files changed, 282 insertions(+), 257 deletions(-) diff --git a/solidity_examples/BECToken.sol b/solidity_examples/BECToken.sol index b03a20e5..bc4b9db4 100644 --- a/solidity_examples/BECToken.sol +++ b/solidity_examples/BECToken.sol @@ -1,29 +1,29 @@ -pragma solidity ^0.4.16; +pragma solidity 0.5.0; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { - function mul(uint256 a, uint256 b) internal constant returns (uint256) { + function mul(uint256 a, uint256 b) internal returns (uint256) { uint256 c = a * b; assert(a == 0 || c / a == b); return c; } - function div(uint256 a, uint256 b) internal constant returns (uint256) { + function div(uint256 a, uint256 b) internal 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) { + function sub(uint256 a, uint256 b) internal returns (uint256) { assert(b <= a); return a - b; } - function add(uint256 a, uint256 b) internal constant returns (uint256) { + function add(uint256 a, uint256 b) internal returns (uint256) { uint256 c = a + b; assert(c >= a); return c; @@ -37,7 +37,7 @@ library SafeMath { */ contract ERC20Basic { uint256 public totalSupply; - function balanceOf(address who) public constant returns (uint256); + function balanceOf(address who) public returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } @@ -63,7 +63,7 @@ contract BasicToken is ERC20Basic { // 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); + emit Transfer(msg.sender, _to, _value); return true; } @@ -72,7 +72,7 @@ contract BasicToken is ERC20Basic { * @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) { + function balanceOf(address _owner) public returns (uint256 balance) { return balances[_owner]; } } @@ -82,7 +82,7 @@ contract BasicToken is ERC20Basic { * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { - function allowance(address owner, address spender) public constant returns (uint256); + function allowance(address owner, address spender) public 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); @@ -115,7 +115,7 @@ contract StandardToken is ERC20, BasicToken { 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); + emit Transfer(_from, _to, _value); return true; } @@ -131,7 +131,7 @@ contract StandardToken is ERC20, BasicToken { */ function approve(address _spender, uint256 _value) public returns (bool) { allowed[msg.sender][_spender] = _value; - Approval(msg.sender, _spender, _value); + emit Approval(msg.sender, _spender, _value); return true; } @@ -141,7 +141,7 @@ contract StandardToken is ERC20, BasicToken { * @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) { + function allowance(address _owner, address _spender) public returns (uint256 remaining) { return allowed[_owner][_spender]; } } @@ -162,7 +162,7 @@ contract Ownable { * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - function Ownable() { + constructor() public { owner = msg.sender; } @@ -182,7 +182,7 @@ contract Ownable { */ function transferOwnership(address newOwner) onlyOwner public { require(newOwner != address(0)); - OwnershipTransferred(owner, newOwner); + emit OwnershipTransferred(owner, newOwner); owner = newOwner; } @@ -220,7 +220,7 @@ contract Pausable is Ownable { */ function pause() onlyOwner whenNotPaused public { paused = true; - Pause(); + emit Pause(); } /** @@ -228,7 +228,7 @@ contract Pausable is Ownable { */ function unpause() onlyOwner whenPaused public { paused = false; - Unpause(); + emit Unpause(); } } @@ -251,8 +251,8 @@ contract PausableToken is StandardToken, Pausable { 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) { + + function batchTransfer(address[] memory _receivers, uint256 _value) public whenNotPaused returns (bool) { uint cnt = _receivers.length; uint256 amount = uint256(cnt) * _value; require(cnt > 0 && cnt <= 20); @@ -261,7 +261,7 @@ contract PausableToken is StandardToken, Pausable { 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); + emit Transfer(msg.sender, _receivers[i], _value); } return true; } @@ -287,12 +287,12 @@ contract BecToken is PausableToken { /** * @dev Function to check the amount of tokens that an owner allowed to a spender. */ - function BecToken() { + constructor() public { totalSupply = 7000000000 * (10**(uint256(decimals))); balances[msg.sender] = totalSupply; // Give the creator all initial tokens } - function () { + function () external { //if ether is sent to this address, send it back. revert(); } diff --git a/solidity_examples/WalletLibrary.sol b/solidity_examples/WalletLibrary.sol index 90294219..204de6a1 100644 --- a/solidity_examples/WalletLibrary.sol +++ b/solidity_examples/WalletLibrary.sol @@ -9,7 +9,7 @@ // 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; +pragma solidity 0.5.0; contract WalletEvents { // EVENTS @@ -50,15 +50,15 @@ contract WalletAbi { function changeRequirement(uint _newRequired) external; - function isOwner(address _addr) constant returns (bool); + function isOwner(address _addr) public returns (bool); - function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool); + function hasConfirmed(bytes32 _operation, address _owner) external 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); + function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32 o_hash); + function confirm(bytes32 _h) public returns (bool o_success); } contract WalletLibrary is WalletEvents { @@ -96,15 +96,15 @@ contract WalletLibrary is WalletEvents { // METHODS // gets called when no other function matches - function() payable { + function() external payable { // just being sent some cash? if (msg.value > 0) - Deposit(msg.sender, msg.value); + emit 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 { + function initMultiowned(address[] memory _owners, uint _required) public only_uninitialized { m_numOwners = _owners.length + 1; m_owners[1] = uint(msg.sender); m_ownerIndex[uint(msg.sender)] = 1; @@ -122,16 +122,16 @@ contract WalletLibrary is WalletEvents { // make sure they're an owner if (ownerIndex == 0) return; uint ownerIndexBit = 2**ownerIndex; - var pending = m_pending[_operation]; + PendingState memory pending = m_pending[_operation]; if (pending.ownersDone & ownerIndexBit > 0) { pending.yetNeeded++; pending.ownersDone -= ownerIndexBit; - Revoke(msg.sender, _operation); + emit Revoke(msg.sender, _operation); } } // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { + function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) external { if (isOwner(_to)) return; uint ownerIndex = m_ownerIndex[uint(_from)]; if (ownerIndex == 0) return; @@ -140,10 +140,10 @@ contract WalletLibrary is WalletEvents { m_owners[ownerIndex] = uint(_to); m_ownerIndex[uint(_from)] = 0; m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); + emit OwnerChanged(_from, _to); } - function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { + function addOwner(address _owner) onlymanyowners(keccak256(msg.data)) external { if (isOwner(_owner)) return; clearPending(); @@ -154,10 +154,10 @@ contract WalletLibrary is WalletEvents { m_numOwners++; m_owners[m_numOwners] = uint(_owner); m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); + emit OwnerAdded(_owner); } - function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { + function removeOwner(address _owner) onlymanyowners(keccak256(msg.data)) external { uint ownerIndex = m_ownerIndex[uint(_owner)]; if (ownerIndex == 0) return; if (m_required > m_numOwners - 1) return; @@ -166,27 +166,27 @@ contract WalletLibrary is WalletEvents { 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); + emit OwnerRemoved(_owner); } - function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { + function changeRequirement(uint _newRequired) onlymanyowners(keccak256(msg.data)) external { if (_newRequired > m_numOwners) return; m_required = _newRequired; clearPending(); - RequirementChanged(_newRequired); + emit RequirementChanged(_newRequired); } // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) external constant returns (address) { + function getOwner(uint ownerIndex) external returns (address) { return address(m_owners[ownerIndex + 1]); } - function isOwner(address _addr) constant returns (bool) { + function isOwner(address _addr) public returns (bool) { return m_ownerIndex[uint(_addr)] > 0; } - function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) { - var pending = m_pending[_operation]; + function hasConfirmed(bytes32 _operation, address _owner) external returns (bool) { + PendingState memory pending = m_pending[_operation]; uint ownerIndex = m_ownerIndex[uint(_owner)]; // make sure they're an owner @@ -198,85 +198,87 @@ contract WalletLibrary is WalletEvents { } // constructor - stores initial daily limit and records the present day's index. - function initDaylimit(uint _limit) only_uninitialized { + function initDaylimit(uint _limit) public 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 { + function setDailyLimit(uint _newLimit) onlymanyowners(keccak256(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 { + function resetSpentToday() onlymanyowners(keccak256(msg.data)) external { m_spentToday = 0; } // throw unless the contract is not yet initialized. - modifier only_uninitialized { if (m_numOwners > 0) throw; _; } + modifier only_uninitialized { require(m_numOwners > 0); _; } // 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 { + function initWallet(address[] memory _owners, uint _required, uint _daylimit) public 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); + function kill(address payable _to) onlymanyowners(keccak256(msg.data)) external { + selfdestruct(_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) { + function execute(address _to, uint _value, bytes calldata _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) { + if (_to == address(0)) { created = create(_value, _data); } else { - if (!_to.call.value(_value)(_data)) - throw; + (bool success, bytes memory data) = _to.call.value(_value)(_data); + require(success); } - SingleTransact(msg.sender, _value, _to, _data, created); + emit SingleTransact(msg.sender, _value, _to, _data, created); } else { // determine our operation hash. - o_hash = sha3(msg.data, block.number); + o_hash = keccak256(abi.encode(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) { + if (m_txs[o_hash].to == address(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); + emit ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data); } } } - function create(uint _value, bytes _code) internal returns (address o_addr) { + function create(uint _value, bytes memory _code) internal returns (address o_addr) { + uint256 o_size; assembly { o_addr := create(_value, add(_code, 0x20), mload(_code)) - jumpi(0xdeadbeef, iszero(extcodesize(o_addr))) + o_size := extcodesize(o_addr) } + require(o_size != 0); } // 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) { + function confirm(bytes32 _h) public onlymanyowners(_h) returns (bool o_success) { + if (m_txs[_h].to != address(0) || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) { address created; - if (m_txs[_h].to == 0) { + if (m_txs[_h].to == address(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; + (bool success, bytes memory data) = m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data); + require(success); } - MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created); + emit MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created); delete m_txs[_h]; return true; } @@ -288,9 +290,9 @@ contract WalletLibrary is WalletEvents { // determine what index the present sender is: uint ownerIndex = m_ownerIndex[uint(msg.sender)]; // make sure they're an owner - if (ownerIndex == 0) return; + if (ownerIndex == 0) return false; - var pending = m_pending[_operation]; + PendingState memory 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. @@ -304,7 +306,7 @@ contract WalletLibrary is WalletEvents { 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); + emit Confirmation(msg.sender, _operation); // ok - check if count is enough to go ahead. if (pending.yetNeeded <= 1) { // enough confirmations: reset and run interior. @@ -354,7 +356,7 @@ contract WalletLibrary is WalletEvents { } // determines today's index. - function today() private constant returns (uint) { return now / 1 days; } + function today() private returns (uint) { return now / 1 days; } function clearPending() internal { uint length = m_pendingIndex.length; @@ -370,7 +372,7 @@ contract WalletLibrary is WalletEvents { } // FIELDS - address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; + address _walletLibrary = 0xCAfEcAfeCAfECaFeCaFecaFecaFECafECafeCaFe; // the number of owners that must confirm the same operation before it is run. uint public m_required; @@ -384,7 +386,7 @@ contract WalletLibrary is WalletEvents { // list of owners uint[256] m_owners; - uint constant c_maxOwners = 250; + uint c_maxOwners = 250; // index on the list of owners to allow reverse lookup mapping(uint => uint) m_ownerIndex; // the ongoing operations. diff --git a/solidity_examples/calls.sol b/solidity_examples/calls.sol index a9069782..513e31fb 100644 --- a/solidity_examples/calls.sol +++ b/solidity_examples/calls.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.17; +pragma solidity 0.5.0; contract Caller { @@ -8,29 +8,29 @@ contract Caller { uint256 statevar; - function Caller(address addr) { + constructor(address addr) public { fixed_address = addr; } function thisisfine() public { - fixed_address.call(); + fixed_address.call(""); } function reentrancy() public { - fixed_address.call(); + fixed_address.call(""); statevar = 0; } - - function calluseraddress(address addr) { - addr.call(); + + function calluseraddress(address addr) public { + addr.call(""); + } + + function callstoredaddress() public { + stored_address.call(""); } - function callstoredaddress() { - stored_address.call(); - } - - function setstoredaddress(address addr) { + function setstoredaddress(address addr) public { stored_address = addr; - } - + } + } \ No newline at end of file diff --git a/solidity_examples/etherstore.sol b/solidity_examples/etherstore.sol index 38a9177c..7cf90388 100644 --- a/solidity_examples/etherstore.sol +++ b/solidity_examples/etherstore.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract EtherStore { uint256 public withdrawalLimit = 1 ether; @@ -14,7 +17,8 @@ contract EtherStore { require(_weiToWithdraw <= withdrawalLimit); // limit the time allowed to withdraw require(now >= lastWithdrawTime[msg.sender] + 1 weeks); - require(msg.sender.call.value(_weiToWithdraw)()); + (bool success, bytes memory data) = msg.sender.call.value(_weiToWithdraw)(""); + require(success); balances[msg.sender] -= _weiToWithdraw; lastWithdrawTime[msg.sender] = now; } diff --git a/solidity_examples/exceptions.sol b/solidity_examples/exceptions.sol index 95c42da0..6e2632f6 100644 --- a/solidity_examples/exceptions.sol +++ b/solidity_examples/exceptions.sol @@ -1,40 +1,43 @@ +pragma solidity 0.5.0; + + contract Exceptions { uint256[8] myarray; - function assert1() { + function assert1() public { uint256 i = 1; assert(i == 0); } - function assert2() { + function assert2() public { uint256 i = 1; assert(i > 0); } - function assert3(uint256 input) { + function assert3(uint256 input) public { assert(input != 23); } - function requireisfine(uint256 input) { + function requireisfine(uint256 input) public { require(input != 23); } - function divisionby0(uint256 input) { + function divisionby0(uint256 input) public { uint256 i = 1/input; } - function thisisfine(uint256 input) { + function thisisfine(uint256 input) public { if (input > 0) { uint256 i = 1/input; } - } + } - function arrayaccess(uint256 index) { + function arrayaccess(uint256 index) public { uint256 i = myarray[index]; } - function thisisalsofind(uint256 index) { + function thisisalsofind(uint256 index) public { if (index < 8) { uint256 i = myarray[index]; } diff --git a/solidity_examples/hashforether.sol b/solidity_examples/hashforether.sol index a90538ea..f8fe4473 100644 --- a/solidity_examples/hashforether.sol +++ b/solidity_examples/hashforether.sol @@ -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); } } \ No newline at end of file diff --git a/solidity_examples/origin.sol b/solidity_examples/origin.sol index 635c15f4..2ceb10f8 100644 --- a/solidity_examples/origin.sol +++ b/solidity_examples/origin.sol @@ -1,32 +1,33 @@ +pragma solidity 0.5.0; + + contract Origin { address public owner; - /** + /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - function Origin() { + constructor() public { owner = msg.sender; } /** - * @dev Throws if called by any account other than the owner. + * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { - if (tx.origin != owner) { - throw; - } + require(tx.origin != owner); _; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. + * @param newOwner The address to transfer ownership to. */ - function transferOwnership(address newOwner) onlyOwner { + function transferOwnership(address newOwner) public onlyOwner { if (newOwner != address(0)) { owner = newOwner; } diff --git a/solidity_examples/returnvalue.sol b/solidity_examples/returnvalue.sol index 819580f3..88bd8805 100644 --- a/solidity_examples/returnvalue.sol +++ b/solidity_examples/returnvalue.sol @@ -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); } } \ No newline at end of file diff --git a/solidity_examples/rubixi.sol b/solidity_examples/rubixi.sol index 301e9196..c8aa2c77 100644 --- a/solidity_examples/rubixi.sol +++ b/solidity_examples/rubixi.sol @@ -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 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 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 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 returns (uint balancePayout) { + balancePayout = participants[payoutOrder].payout / 1 ether; + } - function collectFeesInEther(uint _amt) onlyowner { - _amt *= 1 ether; - if (_amt > collectedFees) collectAllFees(); + function feesSeperateFromBalanceApproximately() public returns (uint fees) { + fees = collectedFees / 1 ether; + } - if (collectedFees == 0) throw; - - creator.send(_amt); - collectedFees -= _amt; - } + function totalParticipants() public returns (uint count) { + count = participants.length; + } - function collectPercentOfFees(uint _pcent) onlyowner { - if (collectedFees == 0 || _pcent > 100) throw; + function numberOfParticipantsWaitingForPayout() public returns (uint count) { + count = participants.length - payoutOrder; + } - uint feesToCollect = collectedFees / 100 * _pcent; - creator.send(feesToCollect); - collectedFees -= feesToCollect; + function participantDetails(uint orderInPyramid) public 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; } + } } diff --git a/solidity_examples/suicide.sol b/solidity_examples/suicide.sol index 1763365b..9e25678c 100644 --- a/solidity_examples/suicide.sol +++ b/solidity_examples/suicide.sol @@ -1,6 +1,9 @@ +pragma solidity 0.5.0; + + contract Suicide { - function kill(address addr) { + function kill(address payable addr) public { selfdestruct(addr); } diff --git a/solidity_examples/timelock.sol b/solidity_examples/timelock.sol index 33ddb4fe..433a300a 100644 --- a/solidity_examples/timelock.sol +++ b/solidity_examples/timelock.sol @@ -1,3 +1,6 @@ +pragma solidity 0.5.0; + + contract TimeLock { mapping(address => uint) public balances; diff --git a/solidity_examples/token.sol b/solidity_examples/token.sol index 19239427..0e03d9ee 100644 --- a/solidity_examples/token.sol +++ b/solidity_examples/token.sol @@ -1,11 +1,12 @@ -pragma solidity ^0.4.18; +pragma solidity 0.5.0; + contract Token { mapping(address => uint) balances; uint public totalSupply; - function Token(uint _initialSupply) { + constructor(uint _initialSupply) public { balances[msg.sender] = totalSupply = _initialSupply; } @@ -16,7 +17,7 @@ contract Token { return true; } - function balanceOf(address _owner) public constant returns (uint balance) { + function balanceOf(address _owner) public returns (uint balance) { return balances[_owner]; } } \ No newline at end of file diff --git a/solidity_examples/weak_random.sol b/solidity_examples/weak_random.sol index 88fc4e12..5acdd7ef 100644 --- a/solidity_examples/weak_random.sol +++ b/solidity_examples/weak_random.sol @@ -1,20 +1,21 @@ -pragma solidity ^0.4.16; +pragma solidity 0.5.0; + contract WeakRandom { struct Contestant { - address addr; + address payable addr; uint gameId; } - uint public constant prize = 2.5 ether; - uint public constant totalTickets = 50; - uint public constant pricePerTicket = prize / totalTickets; + uint public prize = 2.5 ether; + uint public totalTickets = 50; + uint public pricePerTicket = prize / totalTickets; uint public gameId = 1; uint public nextTicket = 0; mapping (uint => Contestant) public contestants; - function () payable public { + function () payable external { uint moneySent = msg.value; while (moneySent >= pricePerTicket && nextTicket < totalTickets) { @@ -37,10 +38,10 @@ contract WeakRandom { address seed1 = contestants[uint(block.coinbase) % totalTickets].addr; address seed2 = contestants[uint(msg.sender) % totalTickets].addr; uint seed3 = block.difficulty; - bytes32 randHash = keccak256(seed1, seed2, seed3); + bytes32 randHash = keccak256(abi.encode(seed1, seed2, seed3)); uint winningNumber = uint(randHash) % totalTickets; - address winningAddress = contestants[winningNumber].addr; + address payable winningAddress = contestants[winningNumber].addr; gameId++; nextTicket = 0; From d226755ae9f2206676eab54d38dc420b7d705d80 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Mon, 26 Nov 2018 13:50:40 +0100 Subject: [PATCH 09/14] Fix test contract modifiers --- tests/testdata/input_contracts/ether_send.sol | 2 +- tests/testdata/input_contracts/exceptions.sol | 16 ++++++++-------- .../testdata/input_contracts/kinds_of_calls.sol | 2 +- tests/testdata/input_contracts/overflow.sol | 2 +- tests/testdata/input_contracts/rubixi.sol | 16 ++++++++-------- tests/testdata/input_contracts/underflow.sol | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/testdata/input_contracts/ether_send.sol b/tests/testdata/input_contracts/ether_send.sol index 23f20ff6..59e1e245 100644 --- a/tests/testdata/input_contracts/ether_send.sol +++ b/tests/testdata/input_contracts/ether_send.sol @@ -27,7 +27,7 @@ contract Crowdfunding { balances[msg.sender] += msg.value; } - function getBalance() public returns (uint) { + function getBalance() public view returns (uint) { return balances[msg.sender]; } diff --git a/tests/testdata/input_contracts/exceptions.sol b/tests/testdata/input_contracts/exceptions.sol index 6e2632f6..aa925603 100644 --- a/tests/testdata/input_contracts/exceptions.sol +++ b/tests/testdata/input_contracts/exceptions.sol @@ -5,39 +5,39 @@ contract Exceptions { uint256[8] myarray; - function assert1() public { + function assert1() public pure { uint256 i = 1; assert(i == 0); } - function assert2() public { + function assert2() public pure { uint256 i = 1; assert(i > 0); } - function assert3(uint256 input) public { + function assert3(uint256 input) public pure { assert(input != 23); } - function requireisfine(uint256 input) public { + function requireisfine(uint256 input) public pure { require(input != 23); } - function divisionby0(uint256 input) public { + function divisionby0(uint256 input) public pure { uint256 i = 1/input; } - function thisisfine(uint256 input) public { + function thisisfine(uint256 input) public pure { if (input > 0) { uint256 i = 1/input; } } - function arrayaccess(uint256 index) public { + function arrayaccess(uint256 index) public view { uint256 i = myarray[index]; } - function thisisalsofind(uint256 index) public { + function thisisalsofind(uint256 index) public view { if (index < 8) { uint256 i = myarray[index]; } diff --git a/tests/testdata/input_contracts/kinds_of_calls.sol b/tests/testdata/input_contracts/kinds_of_calls.sol index 10cec2cd..2b1cb8c4 100644 --- a/tests/testdata/input_contracts/kinds_of_calls.sol +++ b/tests/testdata/input_contracts/kinds_of_calls.sol @@ -9,7 +9,7 @@ contract D { _e.call(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); } - function callcodeSetN(address _e, uint _n) public { + function callcodeSetN(address _e, uint _n) public view { _e.staticcall(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); } diff --git a/tests/testdata/input_contracts/overflow.sol b/tests/testdata/input_contracts/overflow.sol index 52d0c9d9..d1d3d875 100644 --- a/tests/testdata/input_contracts/overflow.sol +++ b/tests/testdata/input_contracts/overflow.sol @@ -17,7 +17,7 @@ contract Over { return true; } - function balanceOf(address _owner) public returns (uint balance) { + function balanceOf(address _owner) public view returns (uint balance) { return balances[_owner]; } } diff --git a/tests/testdata/input_contracts/rubixi.sol b/tests/testdata/input_contracts/rubixi.sol index c8aa2c77..8e1567c6 100644 --- a/tests/testdata/input_contracts/rubixi.sol +++ b/tests/testdata/input_contracts/rubixi.sol @@ -73,38 +73,38 @@ contract Rubixi { } //Functions to provide information to end-user using JSON interface or other interfaces - function currentMultiplier() public returns (uint multiplier, string memory info) { + 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 returns (uint fee, string memory info) { + 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%)"; } - function currentPyramidBalanceApproximately() public returns (uint pyramidBalance, string memory info) { + 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"; } - function nextPayoutWhenPyramidBalanceTotalsApproximately() public returns (uint balancePayout) { + function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) { balancePayout = participants[payoutOrder].payout / 1 ether; } - function feesSeperateFromBalanceApproximately() public returns (uint fees) { + function feesSeperateFromBalanceApproximately() public view returns (uint fees) { fees = collectedFees / 1 ether; } - function totalParticipants() public returns (uint count) { + function totalParticipants() public view returns (uint count) { count = participants.length; } - function numberOfParticipantsWaitingForPayout() public returns (uint count) { + function numberOfParticipantsWaitingForPayout() public view returns (uint count) { count = participants.length - payoutOrder; } - function participantDetails(uint orderInPyramid) public returns (address addr, uint payout) { + 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; diff --git a/tests/testdata/input_contracts/underflow.sol b/tests/testdata/input_contracts/underflow.sol index c1f872f5..01ed4ef9 100644 --- a/tests/testdata/input_contracts/underflow.sol +++ b/tests/testdata/input_contracts/underflow.sol @@ -17,7 +17,7 @@ contract Under { return true; } - function balanceOf(address _owner) public returns (uint balance) { + function balanceOf(address _owner) public view returns (uint balance) { return balances[_owner]; } } \ No newline at end of file From a047f564b3b0f8fa0c2bf127c6f6bf5f64d591bf Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Mon, 26 Nov 2018 13:57:34 +0100 Subject: [PATCH 10/14] Fix example contract modifiers --- solidity_examples/BECToken.sol | 8 ++++---- solidity_examples/WalletLibrary.sol | 8 ++++---- solidity_examples/exceptions.sol | 16 ++++++++-------- solidity_examples/rubixi.sol | 16 ++++++++-------- solidity_examples/token.sol | 2 +- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/solidity_examples/BECToken.sol b/solidity_examples/BECToken.sol index bc4b9db4..3a14fd12 100644 --- a/solidity_examples/BECToken.sol +++ b/solidity_examples/BECToken.sol @@ -5,25 +5,25 @@ pragma solidity 0.5.0; * @dev Math operations with safety checks that throw on error */ library SafeMath { - function mul(uint256 a, uint256 b) internal returns (uint256) { + function mul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; assert(a == 0 || c / a == b); return c; } - function div(uint256 a, uint256 b) internal returns (uint256) { + function div(uint256 a, uint256 b) internal pure 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 returns (uint256) { + function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } - function add(uint256 a, uint256 b) internal returns (uint256) { + function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; diff --git a/solidity_examples/WalletLibrary.sol b/solidity_examples/WalletLibrary.sol index 204de6a1..d972cdd6 100644 --- a/solidity_examples/WalletLibrary.sol +++ b/solidity_examples/WalletLibrary.sol @@ -177,15 +177,15 @@ contract WalletLibrary is WalletEvents { } // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) external returns (address) { + function getOwner(uint ownerIndex) external view returns (address) { return address(m_owners[ownerIndex + 1]); } - function isOwner(address _addr) public returns (bool) { + function isOwner(address _addr) public view returns (bool) { return m_ownerIndex[uint(_addr)] > 0; } - function hasConfirmed(bytes32 _operation, address _owner) external returns (bool) { + function hasConfirmed(bytes32 _operation, address _owner) external view returns (bool) { PendingState memory pending = m_pending[_operation]; uint ownerIndex = m_ownerIndex[uint(_owner)]; @@ -356,7 +356,7 @@ contract WalletLibrary is WalletEvents { } // determines today's index. - function today() private returns (uint) { return now / 1 days; } + function today() private view returns (uint) { return now / 1 days; } function clearPending() internal { uint length = m_pendingIndex.length; diff --git a/solidity_examples/exceptions.sol b/solidity_examples/exceptions.sol index 6e2632f6..aa925603 100644 --- a/solidity_examples/exceptions.sol +++ b/solidity_examples/exceptions.sol @@ -5,39 +5,39 @@ contract Exceptions { uint256[8] myarray; - function assert1() public { + function assert1() public pure { uint256 i = 1; assert(i == 0); } - function assert2() public { + function assert2() public pure { uint256 i = 1; assert(i > 0); } - function assert3(uint256 input) public { + function assert3(uint256 input) public pure { assert(input != 23); } - function requireisfine(uint256 input) public { + function requireisfine(uint256 input) public pure { require(input != 23); } - function divisionby0(uint256 input) public { + function divisionby0(uint256 input) public pure { uint256 i = 1/input; } - function thisisfine(uint256 input) public { + function thisisfine(uint256 input) public pure { if (input > 0) { uint256 i = 1/input; } } - function arrayaccess(uint256 index) public { + function arrayaccess(uint256 index) public view { uint256 i = myarray[index]; } - function thisisalsofind(uint256 index) public { + function thisisalsofind(uint256 index) public view { if (index < 8) { uint256 i = myarray[index]; } diff --git a/solidity_examples/rubixi.sol b/solidity_examples/rubixi.sol index c8aa2c77..8e1567c6 100644 --- a/solidity_examples/rubixi.sol +++ b/solidity_examples/rubixi.sol @@ -73,38 +73,38 @@ contract Rubixi { } //Functions to provide information to end-user using JSON interface or other interfaces - function currentMultiplier() public returns (uint multiplier, string memory info) { + 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 returns (uint fee, string memory info) { + 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%)"; } - function currentPyramidBalanceApproximately() public returns (uint pyramidBalance, string memory info) { + 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"; } - function nextPayoutWhenPyramidBalanceTotalsApproximately() public returns (uint balancePayout) { + function nextPayoutWhenPyramidBalanceTotalsApproximately() public view returns (uint balancePayout) { balancePayout = participants[payoutOrder].payout / 1 ether; } - function feesSeperateFromBalanceApproximately() public returns (uint fees) { + function feesSeperateFromBalanceApproximately() public view returns (uint fees) { fees = collectedFees / 1 ether; } - function totalParticipants() public returns (uint count) { + function totalParticipants() public view returns (uint count) { count = participants.length; } - function numberOfParticipantsWaitingForPayout() public returns (uint count) { + function numberOfParticipantsWaitingForPayout() public view returns (uint count) { count = participants.length - payoutOrder; } - function participantDetails(uint orderInPyramid) public returns (address addr, uint payout) { + 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; diff --git a/solidity_examples/token.sol b/solidity_examples/token.sol index 0e03d9ee..30eeb963 100644 --- a/solidity_examples/token.sol +++ b/solidity_examples/token.sol @@ -17,7 +17,7 @@ contract Token { return true; } - function balanceOf(address _owner) public returns (uint balance) { + function balanceOf(address _owner) public view returns (uint balance) { return balances[_owner]; } } \ No newline at end of file From c600ddc3e5f30ae2055bd3f2af59cd80a49fb47a Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Mon, 26 Nov 2018 20:41:03 +0700 Subject: [PATCH 11/14] Make infura-mainnet the default option in CLI (#751) * Make infura-mainnet tbhe default option in CLI * Black formatting --- mythril/interfaces/cli.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index 8f52f8b5..53019fcf 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -200,13 +200,12 @@ def main(): ) rpc = parser.add_argument_group("RPC options") - rpc.add_argument( - "-i", action="store_true", help="Preset: Infura Node service (Mainnet)" - ) + rpc.add_argument( "--rpc", help="custom RPC settings", metavar="HOST:PORT / ganache / infura-[network_name]", + default="infura-mainnet", ) rpc.add_argument( "--rpctls", type=bool, default=False, help="RPC connection over TLS" @@ -290,12 +289,7 @@ def main(): if args.address: # Establish RPC connection if necessary - if args.i: - mythril.set_api_rpc_infura() - elif args.rpc: - mythril.set_api_rpc(rpc=args.rpc, rpctls=args.rpctls) - elif not (args.dynld or not args.no_onchain_storage_access): - mythril.set_api_rpc_localhost() + mythril.set_api_rpc(rpc=args.rpc, rpctls=args.rpctls) elif args.search or args.contract_hash_to_address: # Open LevelDB if necessary mythril.set_api_leveldb( From 1884d4c79f5c91b691e5387bc535aab3326212c7 Mon Sep 17 00:00:00 2001 From: Luca Daniel Date: Mon, 26 Nov 2018 16:34:14 +0200 Subject: [PATCH 12/14] Trim 0x prefix on codecopy state transition (Issue #705) (#729) * Trim 0x prefix on codecopy state transition * Trimming 0x before sending to `load_from_bytecode()` * Delete config.ini * Remove unused trim0x function * Reformat instructions.py with black * Update mythril/interfaces/cli.py More idiomatic, thanks Co-Authored-By: cleanunicorn * Changes based on review, more idiomatic * Trim 0x with oneliner if for code loaded from file --- mythril/interfaces/cli.py | 4 +++- mythril/laser/ethereum/instructions.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index 53019fcf..90a5975d 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -325,9 +325,11 @@ def main(): if args.code: # Load from bytecode - address, _ = mythril.load_from_bytecode(args.code, args.bin_runtime) + code = args.code[2:] if args.code.startswith("0x") else args.code + address, _ = mythril.load_from_bytecode(code, args.bin_runtime) elif args.codefile: bytecode = "".join([l.strip() for l in args.codefile if len(l.strip()) > 0]) + bytecode = bytecode[2:] if bytecode.startswith("0x") else bytecode address, _ = mythril.load_from_bytecode(bytecode, args.bin_runtime) elif args.address: # Get bytecode from a contract address diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index 4cbc06c5..7ade087d 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -706,7 +706,7 @@ class Instruction: if size == 0 and isinstance( global_state.current_transaction, ContractCreationTransaction ): - if concrete_code_offset >= len(global_state.environment.code.bytecode) // 2: + if concrete_code_offset >= len(bytecode) // 2: global_state.mstate.mem_extend(concrete_memory_offset, 1) global_state.mstate.memory[ concrete_memory_offset From c4127fd229c40e145f4d2826571af81bede09d05 Mon Sep 17 00:00:00 2001 From: Dominik Muhs Date: Mon, 26 Nov 2018 15:47:33 +0100 Subject: [PATCH 13/14] Add Ubuntu PPA support to solc installer, fix version to 0.5.0 --- mythril/ethereum/util.py | 20 +++---- mythril/mythril.py | 53 +++++++++---------- tests/cmd_line_test.py | 8 ++- .../transaction/create_transaction_test.py | 4 +- tests/native_test.py | 2 +- tests/solidity_contract_test.py | 6 +-- tests/svm_test.py | 2 +- 7 files changed, 46 insertions(+), 49 deletions(-) diff --git a/mythril/ethereum/util.py b/mythril/ethereum/util.py index 6669dadc..9c5a3fce 100644 --- a/mythril/ethereum/util.py +++ b/mythril/ethereum/util.py @@ -73,12 +73,14 @@ def get_indexed_address(index): def solc_exists(version): - solc_binary = os.path.join( - os.environ.get("HOME", str(Path.home())), - ".py-solc/solc-v" + version, - "bin/solc", - ) - if os.path.exists(solc_binary): - return True - else: - return False + solc_binaries = [ + os.path.join( + os.environ.get("HOME", str(Path.home())), + ".py-solc/solc-v" + version, + "bin/solc", + ), # py-solc setup + "/usr/bin/solc", # Ubuntu PPA setup + ] + for solc_path in solc_binaries: + if os.path.exists(solc_path): + return solc_path diff --git a/mythril/mythril.py b/mythril/mythril.py index ef74c645..3c7c7b5f 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -224,36 +224,33 @@ class Mythril(object): # Figure out solc binary and version # Only proper versions are supported. No nightlies, commits etc (such as available in remix) - if version: - # tried converting input to semver, seemed not necessary so just slicing for now - if version == str(solc.main.get_solc_version())[:6]: - logging.info("Given version matches installed version") - try: - solc_binary = os.environ["SOLC"] - except KeyError: - solc_binary = "solc" - else: - if util.solc_exists(version): - logging.info("Given version is already installed") - else: - try: - solc.install_solc("v" + version) - except SolcError: - raise CriticalError( - "There was an error when trying to install the specified solc version" - ) + if not version: + return os.environ.get("SOLC") or "solc" - solc_binary = os.path.join( - os.environ.get("HOME", str(Path.home())), - ".py-solc/solc-v" + version, - "bin/solc", - ) - logging.info("Setting the compiler to " + str(solc_binary)) + # tried converting input to semver, seemed not necessary so just slicing for now + main_version = solc.main.get_solc_version_string() + main_version_number = re.match(r"\d+.\d+.\d+", main_version) + if main_version is None: + raise CriticalError( + "Could not extract solc version from string {}".format(main_version) + ) + if version == main_version_number: + logging.info("Given version matches installed version") + solc_binary = os.environ.get("SOLC") or "solc" else: - try: - solc_binary = os.environ["SOLC"] - except KeyError: - solc_binary = "solc" + solc_binary = util.solc_exists(version) + if solc_binary: + logging.info("Given version is already installed") + else: + try: + solc.install_solc("v" + version) + except SolcError: + raise CriticalError( + "There was an error when trying to install the specified solc version" + ) + + logging.info("Setting the compiler to %s", solc_binary) + return solc_binary def set_api_leveldb(self, leveldb): diff --git a/tests/cmd_line_test.py b/tests/cmd_line_test.py index ef846480..bc45adbd 100644 --- a/tests/cmd_line_test.py +++ b/tests/cmd_line_test.py @@ -10,18 +10,16 @@ def output_of(command): class CommandLineToolTestCase(BaseTestCase): def test_disassemble_code_correctly(self): - command = "python3 {} MYTH -d --bin-runtime -c 0x5050 --solv 0.4.24".format( - MYTH - ) + command = "python3 {} MYTH -d --bin-runtime -c 0x5050 --solv 0.5.0".format(MYTH) self.assertIn("0 POP\n1 POP\n", output_of(command)) def test_disassemble_solidity_file_correctly(self): solidity_file = str(TESTDATA / "input_contracts" / "metacoin.sol") - command = "python3 {} -d {} --solv 0.4.24".format(MYTH, solidity_file) + command = "python3 {} -d {} --solv 0.5.0".format(MYTH, solidity_file) self.assertIn("2 PUSH1 0x40\n4 MSTORE", output_of(command)) def test_hash_a_function_correctly(self): - command = "python3 {} --solv 0.4.24 --hash 'setOwner(address)'".format(MYTH) + command = "python3 {} --solv 0.5.0 --hash 'setOwner(address)'".format(MYTH) self.assertIn("0x13af4035\n", output_of(command)) diff --git a/tests/laser/transaction/create_transaction_test.py b/tests/laser/transaction/create_transaction_test.py index 643e9efb..9b2351e4 100644 --- a/tests/laser/transaction/create_transaction_test.py +++ b/tests/laser/transaction/create_transaction_test.py @@ -13,7 +13,7 @@ from mythril.analysis.symbolic import SymExecWrapper def test_create(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) laser_evm = svm.LaserEVM({}) @@ -37,7 +37,7 @@ def test_create(): def test_sym_exec(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) sym = SymExecWrapper( diff --git a/tests/native_test.py b/tests/native_test.py index cf5c2d77..a19e86fd 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -89,7 +89,7 @@ class NativeTests(BaseTestCase): def runTest(): disassembly = SolidityContract( - "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.4.24") + "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account} diff --git a/tests/solidity_contract_test.py b/tests/solidity_contract_test.py index ba5d9919..6b55aad1 100644 --- a/tests/solidity_contract_test.py +++ b/tests/solidity_contract_test.py @@ -11,7 +11,7 @@ class SolidityContractTest(BaseTestCase): def test_get_source_info_without_name_gets_latest_contract_info(self): input_file = TEST_FILES / "multi_contracts.sol" contract = SolidityContract( - str(input_file), solc_binary=Mythril._init_solc_binary("0.4.24") + str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0") ) code_info = contract.get_source_info(142) @@ -25,7 +25,7 @@ class SolidityContractTest(BaseTestCase): contract = SolidityContract( str(input_file), name="Transfer1", - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) code_info = contract.get_source_info(142) @@ -39,7 +39,7 @@ class SolidityContractTest(BaseTestCase): contract = SolidityContract( str(input_file), name="AssertFail", - solc_binary=Mythril._init_solc_binary("0.4.24"), + solc_binary=Mythril._init_solc_binary("0.5.0"), ) code_info = contract.get_source_info(70, constructor=True) diff --git a/tests/svm_test.py b/tests/svm_test.py index e2f31a91..b687e944 100644 --- a/tests/svm_test.py +++ b/tests/svm_test.py @@ -84,7 +84,7 @@ class SVMTestCase(BaseTestCase): ) disassembly = SolidityContract( - str(input_file), solc_binary=Mythril._init_solc_binary("0.4.24") + str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account} From ecc305102b15544cd5f94bd5c5ef580e9f9d3dd4 Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Tue, 27 Nov 2018 09:22:20 +0700 Subject: [PATCH 14/14] Remove string prefix from debugging output --- mythril/analysis/modules/ether_thief.py | 2 +- mythril/analysis/modules/exceptions.py | 2 +- mythril/analysis/modules/integer.py | 4 ++-- mythril/analysis/modules/suicide.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mythril/analysis/modules/ether_thief.py b/mythril/analysis/modules/ether_thief.py index c304fb11..93a792d3 100644 --- a/mythril/analysis/modules/ether_thief.py +++ b/mythril/analysis/modules/ether_thief.py @@ -78,7 +78,7 @@ class EtherThief(DetectionModule): ], ) - debug = "Transaction Sequence: " + str(transaction_sequence) + debug = str(transaction_sequence) issue = Issue( contract=node.contract_name, diff --git a/mythril/analysis/modules/exceptions.py b/mythril/analysis/modules/exceptions.py index 2b17920b..41a6a8e8 100644 --- a/mythril/analysis/modules/exceptions.py +++ b/mythril/analysis/modules/exceptions.py @@ -42,7 +42,7 @@ class ReachableExceptionsModule(DetectionModule): "Use `require()` for regular input checking." ) - debug = "Transaction Sequence: " + str( + debug = str( solver.get_transaction_sequence(state, node.constraints) ) diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index e7d67836..9bd354a7 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -108,7 +108,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): operator ) try: - issue.debug = "Transaction Sequence: " + str( + issue.debug = str( solver.get_transaction_sequence(state, node.constraints + [constraint]) ) except UnsatError: @@ -223,7 +223,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): "The subtraction can result in an integer underflow.\n" ) - issue.debug = "Transaction Sequence: " + str( + issue.debug = str( solver.get_transaction_sequence(state, node.constraints) ) issues.append(issue) diff --git a/mythril/analysis/modules/suicide.py b/mythril/analysis/modules/suicide.py index d49d1e0c..9f01848e 100644 --- a/mythril/analysis/modules/suicide.py +++ b/mythril/analysis/modules/suicide.py @@ -46,7 +46,7 @@ def _analyze_state(state): "The contract can be killed by anyone. Don't accidentally kill it." ) - debug = "Transaction Sequence: " + str(transaction_sequence) + debug = str(transaction_sequence) issue = Issue( contract=node.contract_name,