0

I am trying to deploy smartBillions contract on remix for learning purposes. And following error is persisted

creation of SmartBillions errored: transaction execution failed

Following is the code

pragma solidity ^0.4.17;

library SafeMath {
  function sub(uint a, uint b) internal pure returns (uint) {
    assert(b <= a);
    return a - b;
  }
  function add(uint a, uint b) internal pure returns (uint) {
    uint c = a + b;
    assert(c >= a);
    return c;
  }
}

contract ERC20Basic {
  uint public totalSupply;
  address public owner; //owner
  address public animator; //animator
  function balanceOf(address who) constant public returns (uint);
  function transfer(address to, uint value) public;
  event Transfer(address indexed from, address indexed to, uint value);
  function commitDividend(address who) internal; // pays remaining dividend
}

contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender) constant public returns (uint);
  function transferFrom(address from, address to, uint value) public;
  function approve(address spender, uint value) public;
  event Approval(address indexed owner, address indexed spender, uint value);
}

contract BasicToken is ERC20Basic {
  using SafeMath for uint;
  mapping(address => uint) balances;

  modifier onlyPayloadSize(uint size) {
     assert(msg.data.length >= size + 4);
     _;
  }

  function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
    commitDividend(msg.sender);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    if(_to == address(this)) {
        commitDividend(owner);
        balances[owner] = balances[owner].add(_value);
        Transfer(msg.sender, owner, _value);
    }
    else {
        commitDividend(_to);
        balances[_to] = balances[_to].add(_value);
        Transfer(msg.sender, _to, _value);
    }
  }

  function balanceOf(address _owner) constant public returns (uint balance) {
    return balances[_owner];
  }
}

contract StandardToken is BasicToken, ERC20 {
  mapping (address => mapping (address => uint)) allowed;


  function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
    var _allowance = allowed[_from][msg.sender];
    commitDividend(_from);
    commitDividend(_to);
    allowed[_from][msg.sender] = _allowance.sub(_value);
    balances[_from] = balances[_from].sub(_value);
    balances[_to] = balances[_to].add(_value);
    Transfer(_from, _to, _value);
  }

  function approve(address _spender, uint _value) public {
    //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    assert(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));
    allowed[msg.sender][_spender] = _value;
    Approval(msg.sender, _spender, _value);
  }

  function allowance(address _owner, address _spender) constant public returns (uint remaining) {
    return allowed[_owner][_spender];
  }
}


contract SmartBillions is StandardToken {

    // metadata
    string public constant name = "SmartBillions Token";
    string public constant symbol = "Smart"; // changed due to conflicts
    uint public constant decimals = 0;

    // contract state
    struct Wallet {
        uint208 balance; // current balance of user
        uint16 lastDividendPeriod; // last processed dividend period of user's tokens
        uint32 nextWithdrawTime; // next withdrawal possible after this timestamp
    }
    mapping (address => Wallet) wallets;
    struct Bet {
        uint192 value; // bet size
        uint32 betHash; // selected numbers
        uint32 blockNum; // blocknumber when lottery runs
    }
    mapping (address => Bet) bets;

    uint public walletBalance = 0; // sum of funds in wallets

    // investment parameters
    uint public investStart = 1; // investment start block, 0: closed, 1: preparation
    uint public investBalance = 0; // funding from investors
    uint public investBalanceGot = 0; // funding collected
    uint public investBalanceMax = 200000 ether; // maximum funding
    uint public dividendPeriod = 1;
    uint[] public dividends; // dividens collected per period, growing array

    // betting parameters
    uint public maxWin = 0; // maximum prize won
    uint public hashFirst = 0; // start time of building hashes database
    uint public hashLast = 0; // last saved block of hashes
    uint public hashNext = 0; // next available bet block.number
    uint public hashBetSum = 0; // used bet volume of next block
    uint public hashBetMax = 5 ether; // maximum bet size per block
    uint[] public hashes; // space for storing lottery results

    // constants
    uint public constant hashesSize = 16384 ; // 30 days of blocks
    uint public coldStoreLast = 0 ; // timestamp of last cold store transfer

    // events
    event LogBet(address indexed player, uint bethash, uint blocknumber, uint betsize);
    event LogLoss(address indexed player, uint bethash, uint hash);
    event LogWin(address indexed player, uint bethash, uint hash, uint prize);
    event LogInvestment(address indexed investor, address indexed partner, uint amount);
    event LogRecordWin(address indexed player, uint amount);
    event LogLate(address indexed player,uint playerBlockNumber,uint currentBlockNumber);
    event LogDividend(address indexed investor, uint amount, uint period);

    modifier onlyOwner() {
        assert(msg.sender == owner);
        _;
    }

    modifier onlyAnimator() {
        assert(msg.sender == animator);
        _;
    }

    // constructor
    function SmartBillions() public {
        owner = msg.sender;
        animator = msg.sender;
        wallets[owner].lastDividendPeriod = uint16(dividendPeriod);
        dividends.push(0); // not used
        dividends.push(0); // current dividend
    }


    function hashesLength() constant external returns (uint) {
        return uint(hashes.length);
    }


    function walletBalanceOf(address _owner) constant external returns (uint) {
        return uint(wallets[_owner].balance);
    }


    function walletPeriodOf(address _owner) constant external returns (uint) {
        return uint(wallets[_owner].lastDividendPeriod);
    }


    function walletTimeOf(address _owner) constant external returns (uint) {
        return uint(wallets[_owner].nextWithdrawTime);
    }

    function betValueOf(address _owner) constant external returns (uint) {
        return uint(bets[_owner].value);
    }


    function betHashOf(address _owner) constant external returns (uint) {
        return uint(bets[_owner].betHash);
    }


    function betBlockNumberOf(address _owner) constant external returns (uint) {
        return uint(bets[_owner].blockNum);
    }

    function dividendsBlocks() constant external returns (uint) {
        if(investStart > 0) {
            return(0);
        }
        uint period = (block.number - hashFirst) / (10 * hashesSize);
        if(period > dividendPeriod) {
            return(0);
        }
        return((10 * hashesSize) - ((block.number - hashFirst) % (10 * hashesSize)));
    }


    function changeOwner(address _who) external onlyOwner {
        assert(_who != address(0));
        commitDividend(msg.sender);
        commitDividend(_who);
        owner = _who;
    }


    function changeAnimator(address _who) external onlyAnimator {
        assert(_who != address(0));
        commitDividend(msg.sender);
        commitDividend(_who);
        animator = _who;
    }


    function setInvestStart(uint _when) external onlyOwner {
        require(investStart == 1 && hashFirst > 0 && block.number < _when);
        investStart = _when;
    }

    function setBetMax(uint _maxsum) external onlyOwner {
        hashBetMax = _maxsum;
    }


    function resetBet() external onlyOwner {
        hashNext = block.number + 3;
        hashBetSum = 0;
    }


    function coldStore(uint _amount) external onlyOwner {
        houseKeeping();
        require(_amount > 0 && this.balance >= (investBalance * 9 / 10) + walletBalance + _amount);
        if(investBalance >= investBalanceGot / 2){ // additional jackpot protection
            require((_amount <= this.balance / 400) && coldStoreLast + 60 * 60 * 24 * 7 <= block.timestamp);
        }
        msg.sender.transfer(_amount);
        coldStoreLast = block.timestamp;
    }

    /**
     * @dev Move funds to contract jackpot
     */
    function hotStore() payable external {
        walletBalance += msg.value;
        wallets[msg.sender].balance += uint208(msg.value);
        houseKeeping();
    }

/* housekeeping functions */

    /**
     * @dev Update accounting
     */
    function houseKeeping() public {
        if(investStart > 1 && block.number >= investStart + (hashesSize * 5)){ // ca. 14 days
            investStart = 0; // start dividend payments
        }
        else {
            if(hashFirst > 0){
                uint period = (block.number - hashFirst) / (10 * hashesSize );
                if(period > dividends.length - 2) {
                    dividends.push(0);
                }
                if(period > dividendPeriod && investStart == 0 && dividendPeriod < dividends.length - 1) {
                    dividendPeriod++;
                }
            }
        }
    }

/* payments */

    /**
     * @dev Pay balance from wallet
     */
    function payWallet() public {
        if(wallets[msg.sender].balance > 0 && wallets[msg.sender].nextWithdrawTime <= block.timestamp){
            uint balance = wallets[msg.sender].balance;
            wallets[msg.sender].balance = 0;
            walletBalance -= balance;
            pay(balance);
        }
    }

    function pay(uint _amount) private {
        uint maxpay = this.balance / 2;
        if(maxpay >= _amount) {
            msg.sender.transfer(_amount);
            if(_amount > 1 finney) {
                houseKeeping();
            }
        }
        else {
            uint keepbalance = _amount - maxpay;
            walletBalance += keepbalance;
            wallets[msg.sender].balance += uint208(keepbalance);
            wallets[msg.sender].nextWithdrawTime = uint32(block.timestamp + 60 * 60 * 24 * 30); // wait 1 month for more funds
            msg.sender.transfer(maxpay);
        }
    }

/* investment functions */

    function investDirect() payable external {
        invest(owner);
    }


    function invest(address _partner) payable public {
        //require(fromUSA()==false); // fromUSA() not yet implemented :-(
        require(investStart > 1 && block.number < investStart + (hashesSize * 5) && investBalance < investBalanceMax);
        uint investing = msg.value;
        if(investing > investBalanceMax - investBalance) {
            investing = investBalanceMax - investBalance;
            investBalance = investBalanceMax;
            investBalanceGot = investBalanceMax;
            investStart = 0; // close investment round
            msg.sender.transfer(msg.value.sub(investing)); // send back funds immediately
        }
        else{
            investBalance += investing;
            investBalanceGot += investing;
        }
        if(_partner == address(0) || _partner == owner){
            walletBalance += investing / 10;
            wallets[owner].balance += uint208(investing / 10);} // 10% for marketing if no affiliates
        else{
            walletBalance += (investing * 5 / 100) * 2;
            wallets[owner].balance += uint208(investing * 5 / 100); // 5% initial marketing funds
            wallets[_partner].balance += uint208(investing * 5 / 100);} // 5% for affiliates
        wallets[msg.sender].lastDividendPeriod = uint16(dividendPeriod); // assert(dividendPeriod == 1);
        uint senderBalance = investing / 10**15;
        uint ownerBalance = investing * 16 / 10**17  ;
        uint animatorBalance = investing * 10 / 10**17  ;
        balances[msg.sender] += senderBalance;
        balances[owner] += ownerBalance ; // 13% of shares go to developers
        balances[animator] += animatorBalance ; // 8% of shares go to animator
        totalSupply += senderBalance + ownerBalance + animatorBalance;
        Transfer(address(0),msg.sender,senderBalance); // for etherscan
        Transfer(address(0),owner,ownerBalance); // for etherscan
        Transfer(address(0),animator,animatorBalance); // for etherscan
        LogInvestment(msg.sender,_partner,investing);
    }


    function disinvest() external {
        require(investStart == 0);
        commitDividend(msg.sender);
        uint initialInvestment = balances[msg.sender] * 10**15;
        Transfer(msg.sender,address(0),balances[msg.sender]); // for etherscan
        delete balances[msg.sender]; // totalSupply stays the same, investBalance is reduced
        investBalance -= initialInvestment;
        wallets[msg.sender].balance += uint208(initialInvestment * 9 / 10);
        payWallet();
    }


    function payDividends() external {
        require(investStart == 0);
        commitDividend(msg.sender);
        payWallet();
    }

    function commitDividend(address _who) internal {
        uint last = wallets[_who].lastDividendPeriod;
        if((balances[_who]==0) || (last==0)){
            wallets[_who].lastDividendPeriod=uint16(dividendPeriod);
            return;
        }
        if(last==dividendPeriod) {
            return;
        }
        uint share = balances[_who] * 0xffffffff / totalSupply;
        uint balance = 0;
        for(;last<dividendPeriod;last++) {
            balance += share * dividends[last];
        }
        balance = (balance / 0xffffffff);
        walletBalance += balance;
        wallets[_who].balance += uint208(balance);
        wallets[_who].lastDividendPeriod = uint16(last);
        LogDividend(_who,balance,last);
    }

/* lottery functions */

    function betPrize(Bet _player, uint24 _hash) constant private returns (uint) { // house fee 13.85%
        uint24 bethash = uint24(_player.betHash);
        uint24 hit = bethash ^ _hash;
        uint24 matches =
            ((hit & 0xF) == 0 ? 1 : 0 ) +
            ((hit & 0xF0) == 0 ? 1 : 0 ) +
            ((hit & 0xF00) == 0 ? 1 : 0 ) +
            ((hit & 0xF000) == 0 ? 1 : 0 ) +
            ((hit & 0xF0000) == 0 ? 1 : 0 ) +
            ((hit & 0xF00000) == 0 ? 1 : 0 );
        if(matches == 6){
            return(uint(_player.value) * 7000000);
        }
        if(matches == 5){
            return(uint(_player.value) * 20000);
        }
        if(matches == 4){
            return(uint(_player.value) * 500);
        }
        if(matches == 3){
            return(uint(_player.value) * 25);
        }
        if(matches == 2){
            return(uint(_player.value) * 3);
        }
        return(0);
    }

    /**
     * @dev Check if won in lottery
     */
    function betOf(address _who) constant external returns (uint)  {
        Bet memory player = bets[_who];
        if( (player.value==0) ||
            (player.blockNum<=1) ||
            (block.number<player.blockNum) ||
            (block.number>=player.blockNum + (10 * hashesSize))){
            return(0);
        }
        if(block.number<player.blockNum+256){
            return(betPrize(player,uint24(block.blockhash(player.blockNum))));
        }
        if(hashFirst>0){
            uint32 hash = getHash(player.blockNum);
            if(hash == 0x1000000) { // load hash failed :-(, return funds
                return(uint(player.value));
            }
            else{
                return(betPrize(player,uint24(hash)));
            }
    }
        return(0);
    }

    /**
     * @dev Check if won in lottery
     */
    function won() public {
        Bet memory player = bets[msg.sender];
        if(player.blockNum==0){ // create a new player
            bets[msg.sender] = Bet({value: 0, betHash: 0, blockNum: 1});
            return;
        }
        if((player.value==0) || (player.blockNum==1)){
            payWallet();
            return;
        }
        require(block.number>player.blockNum); // if there is an active bet, throw()
        if(player.blockNum + (10 * hashesSize) <= block.number){ // last bet too long ago, lost !
            LogLate(msg.sender,player.blockNum,block.number);
            bets[msg.sender] = Bet({value: 0, betHash: 0, blockNum: 1});
            return;
        }
        uint prize = 0;
        uint32 hash = 0;
        if(block.number<player.blockNum+256){
            hash = uint24(block.blockhash(player.blockNum));
            prize = betPrize(player,uint24(hash));
        }
        else {
            if(hashFirst>0){ // lottery is open even before swap space (hashes) is ready, but player must collect results within 256 blocks after run
                hash = getHash(player.blockNum);
                if(hash == 0x1000000) { // load hash failed :-(
                    //prize = uint(player.value); no refunds anymore
                    LogLate(msg.sender,player.blockNum,block.number);
                    bets[msg.sender] = Bet({value: 0, betHash: 0, blockNum: 1});
                    return();
                }
                else{
                    prize = betPrize(player,uint24(hash));
                }
        }
            else{
                LogLate(msg.sender,player.blockNum,block.number);
                bets[msg.sender] = Bet({value: 0, betHash: 0, blockNum: 1});
                return();
            }
        }
        bets[msg.sender] = Bet({value: 0, betHash: 0, blockNum: 1});
        if(prize>0) {
            LogWin(msg.sender,uint(player.betHash),uint(hash),prize);
            if(prize > maxWin){
                maxWin = prize;
                LogRecordWin(msg.sender,prize);
            }
            pay(prize);
        }
        else{
            LogLoss(msg.sender,uint(player.betHash),uint(hash));
        }
    }


    function () payable external {
        if(msg.value > 0){
            if(investStart>1){ // during ICO payment to the contract is treated as investment
                invest(owner);
            }
            else{ // if not ICO running payment to contract is treated as play
                play();
            }
            return;
        }
        //check for dividends and other assets
        if(investStart == 0 && balances[msg.sender]>0){
            commitDividend(msg.sender);}
        won(); // will run payWallet() if nothing else available
    }

    /**
     * @dev Play in lottery
     */
    function play() payable public returns (uint) {
        return playSystem(uint(keccak256(msg.sender,block.number)), address(0));
    }

    /**
     * @dev Play in lottery with random numbers
     * @param _partner Affiliate partner
     */
    function playRandom(address _partner) payable public returns (uint) {
        return playSystem(uint(keccak256(msg.sender,block.number)), _partner);
    }

    /**
     * @dev Play in lottery with own numbers
     * @param _partner Affiliate partner
     */
    function playSystem(uint _hash, address _partner) payable public returns (uint) {
        won(); // check if player did not win 
        uint24 bethash = uint24(_hash);
        require(msg.value <= 1 ether && msg.value < hashBetMax);
        if(msg.value > 0){
            if(investStart==0) { // dividends only after investment finished
                dividends[dividendPeriod] += msg.value / 20; // 5% dividend
            }
            if(_partner != address(0)) {
                uint fee = msg.value / 100;
                walletBalance += fee;
                wallets[_partner].balance += uint208(fee); // 1% for affiliates
            }
            if(hashNext < block.number + 3) {
                hashNext = block.number + 3;
                hashBetSum = msg.value;
            }
            else{
                if(hashBetSum > hashBetMax) {
                    hashNext++;
                    hashBetSum = msg.value;
                }
                else{
                    hashBetSum += msg.value;
                }
            }
            bets[msg.sender] = Bet({value: uint192(msg.value), betHash: uint32(bethash), blockNum: uint32(hashNext)});
            LogBet(msg.sender,uint(bethash),hashNext,msg.value);
        }
        putHashes(25); // players help collecing data, now much more than in last contract
        return(hashNext);
    }

/* database functions */

    /**
     * @dev Create hash data swap space
     * @param _sadd Number of hashes to add (<=256)
     */
    function addHashes(uint _sadd) public returns (uint) {
        require(hashFirst == 0 && _sadd > 0 && _sadd <= hashesSize);
        uint n = hashes.length;
        if(n + _sadd > hashesSize){
            hashes.length = hashesSize;
        }
        else{
            hashes.length += _sadd;
        }
        for(;n<hashes.length;n++){ // make sure to burn gas
            hashes[n] = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        }
        if(hashes.length>=hashesSize) { // assume block.number > 10
            hashFirst = block.number - ( block.number % 10);
            hashLast = hashFirst;
        }
        return(hashes.length);
    }

    /**
     * @dev Create hash data swap space, add 128 hashes
     */
    function addHashes128() external returns (uint) {
        return(addHashes(128));
    }

    function calcHashes(uint32 _lastb, uint32 _delta) constant private returns (uint) {
        // assert(!(_lastb % 10)); this is required
        return( ( uint(block.blockhash(_lastb  )) & 0xFFFFFF )
            | ( ( uint(block.blockhash(_lastb+1)) & 0xFFFFFF ) << 24 )
            | ( ( uint(block.blockhash(_lastb+2)) & 0xFFFFFF ) << 48 )
            | ( ( uint(block.blockhash(_lastb+3)) & 0xFFFFFF ) << 72 )
            | ( ( uint(block.blockhash(_lastb+4)) & 0xFFFFFF ) << 96 )
            | ( ( uint(block.blockhash(_lastb+5)) & 0xFFFFFF ) << 120 )
            | ( ( uint(block.blockhash(_lastb+6)) & 0xFFFFFF ) << 144 )
            | ( ( uint(block.blockhash(_lastb+7)) & 0xFFFFFF ) << 168 )
            | ( ( uint(block.blockhash(_lastb+8)) & 0xFFFFFF ) << 192 )
            | ( ( uint(block.blockhash(_lastb+9)) & 0xFFFFFF ) << 216 )
            | ( ( uint(_delta) / hashesSize) << 240)); 
    }

    function getHash(uint _block) constant private returns (uint32) {
        uint delta = (_block - hashFirst) / 10;
        uint hash = hashes[delta % hashesSize];
        if(delta / hashesSize != hash >> 240) {
            return(0x1000000); // load failed, incorrect data in hashes
        }
        uint slotp = (_block - hashFirst) % 10; 
        return(uint32((hash >> (24 * slotp)) & 0xFFFFFF));
    }

    /**
     * @dev Fill hash data
     */
    function putHash() public returns (bool) {
        uint lastb = hashLast;
        if(lastb == 0 || block.number <= lastb + 10) {
            return(false);
        }
        if(lastb < block.number - 245) {
            uint num = block.number - 245;
            lastb = num - (num % 10);
        }
        uint delta = (lastb - hashFirst) / 10;
        hashes[delta % hashesSize] = calcHashes(uint32(lastb),uint32(delta));
        hashLast = lastb + 10;
        return(true);
    }

    /**
     * @dev Fill hash data many times
     * @param _num Number of iterations
     */
    function putHashes(uint _num) public {
        uint n=0;
        for(;n<_num;n++){
            if(!putHash()){
                return;
            }
        }
    }

}

closed as unclear what you're asking by Lauri Peltonen, goodvibration, Achala Dissanayake, shane, Rob Hitchens - B9lab Apr 3 at 16:56

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

1

Your problem is that it requires more gas than the 3,000,000 default used by Remix.

If you set "Gas limit" to 6,000,000 in the "Run" tab it should deploy without issues.

  • Thanks it worked. It skipped my mind to think about this issue. – Saeedi Apr 5 at 14:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.