ETH Price: $2,132.70 (+3.03%)

Transaction Decoder

Block:
4312495 at Sep-26-2017 06:14:07 AM +UTC
Transaction Fee:
0.001 ETH $2.13
Gas Used:
250,000 Gas / 4 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x47286e5B...3Cc2Ab326
0.036336942 Eth
Nonce: 23
0.035336942 Eth
Nonce: 24
0.001
(Ethermine)
263.360620615838031242 Eth263.361620615838031242 Eth0.001

Execution Trace

EtherDelta.depositToken( token=0x8eFFd494eB698cc399AF6231fCcd39E08fd20B15, amount=5 )
  • PIXToken.transferFrom( _from=0x47286e5BD438fdcE00c471C19e224883Cc2Ab326, _to=0x8d12A197cB00D4747a1fe03395095ce2A5CC6819, _value=5 ) => ( success=False )
    File 1 of 2: EtherDelta
    pragma solidity ^0.4.9;
    
    contract SafeMath {
      function safeMul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeSub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function safeAdd(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c>=a && c>=b);
        return c;
      }
    
      function assert(bool assertion) internal {
        if (!assertion) throw;
      }
    }
    
    contract Token {
      /// @return total amount of tokens
      function totalSupply() constant returns (uint256 supply) {}
    
      /// @param _owner The address from which the balance will be retrieved
      /// @return The balance
      function balanceOf(address _owner) constant returns (uint256 balance) {}
    
      /// @notice send `_value` token to `_to` from `msg.sender`
      /// @param _to The address of the recipient
      /// @param _value The amount of token to be transferred
      /// @return Whether the transfer was successful or not
      function transfer(address _to, uint256 _value) returns (bool success) {}
    
      /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
      /// @param _from The address of the sender
      /// @param _to The address of the recipient
      /// @param _value The amount of token to be transferred
      /// @return Whether the transfer was successful or not
      function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
    
      /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
      /// @param _spender The address of the account able to transfer the tokens
      /// @param _value The amount of wei to be approved for transfer
      /// @return Whether the approval was successful or not
      function approve(address _spender, uint256 _value) returns (bool success) {}
    
      /// @param _owner The address of the account owning tokens
      /// @param _spender The address of the account able to transfer the tokens
      /// @return Amount of remaining tokens allowed to spent
      function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
    
      event Transfer(address indexed _from, address indexed _to, uint256 _value);
      event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
      uint public decimals;
      string public name;
    }
    
    contract StandardToken is Token {
    
      function transfer(address _to, uint256 _value) returns (bool success) {
        //Default assumes totalSupply can't be over max (2^256 - 1).
        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
        //Replace the if with this one instead.
        if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
        //if (balances[msg.sender] >= _value && _value > 0) {
          balances[msg.sender] -= _value;
          balances[_to] += _value;
          Transfer(msg.sender, _to, _value);
          return true;
        } else { return false; }
      }
    
      function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        //same as above. Replace this line with the following if you want to protect against wrapping uints.
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
          balances[_to] += _value;
          balances[_from] -= _value;
          allowed[_from][msg.sender] -= _value;
          Transfer(_from, _to, _value);
          return true;
        } else { return false; }
      }
    
      function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
      }
    
      function approve(address _spender, uint256 _value) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
      }
    
      mapping(address => uint256) balances;
    
      mapping (address => mapping (address => uint256)) allowed;
    
      uint256 public totalSupply;
    }
    
    contract ReserveToken is StandardToken, SafeMath {
      address public minter;
      function ReserveToken() {
        minter = msg.sender;
      }
      function create(address account, uint amount) {
        if (msg.sender != minter) throw;
        balances[account] = safeAdd(balances[account], amount);
        totalSupply = safeAdd(totalSupply, amount);
      }
      function destroy(address account, uint amount) {
        if (msg.sender != minter) throw;
        if (balances[account] < amount) throw;
        balances[account] = safeSub(balances[account], amount);
        totalSupply = safeSub(totalSupply, amount);
      }
    }
    
    contract AccountLevels {
      //given a user, returns an account level
      //0 = regular user (pays take fee and make fee)
      //1 = market maker silver (pays take fee, no make fee, gets rebate)
      //2 = market maker gold (pays take fee, no make fee, gets entire counterparty's take fee as rebate)
      function accountLevel(address user) constant returns(uint) {}
    }
    
    contract AccountLevelsTest is AccountLevels {
      mapping (address => uint) public accountLevels;
    
      function setAccountLevel(address user, uint level) {
        accountLevels[user] = level;
      }
    
      function accountLevel(address user) constant returns(uint) {
        return accountLevels[user];
      }
    }
    
    contract EtherDelta is SafeMath {
      address public admin; //the admin address
      address public feeAccount; //the account that will receive fees
      address public accountLevelsAddr; //the address of the AccountLevels contract
      uint public feeMake; //percentage times (1 ether)
      uint public feeTake; //percentage times (1 ether)
      uint public feeRebate; //percentage times (1 ether)
      mapping (address => mapping (address => uint)) public tokens; //mapping of token addresses to mapping of account balances (token=0 means Ether)
      mapping (address => mapping (bytes32 => bool)) public orders; //mapping of user accounts to mapping of order hashes to booleans (true = submitted by user, equivalent to offchain signature)
      mapping (address => mapping (bytes32 => uint)) public orderFills; //mapping of user accounts to mapping of order hashes to uints (amount of order that has been filled)
    
      event Order(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user);
      event Cancel(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s);
      event Trade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, address get, address give);
      event Deposit(address token, address user, uint amount, uint balance);
      event Withdraw(address token, address user, uint amount, uint balance);
    
      function EtherDelta(address admin_, address feeAccount_, address accountLevelsAddr_, uint feeMake_, uint feeTake_, uint feeRebate_) {
        admin = admin_;
        feeAccount = feeAccount_;
        accountLevelsAddr = accountLevelsAddr_;
        feeMake = feeMake_;
        feeTake = feeTake_;
        feeRebate = feeRebate_;
      }
    
      function() {
        throw;
      }
    
      function changeAdmin(address admin_) {
        if (msg.sender != admin) throw;
        admin = admin_;
      }
    
      function changeAccountLevelsAddr(address accountLevelsAddr_) {
        if (msg.sender != admin) throw;
        accountLevelsAddr = accountLevelsAddr_;
      }
    
      function changeFeeAccount(address feeAccount_) {
        if (msg.sender != admin) throw;
        feeAccount = feeAccount_;
      }
    
      function changeFeeMake(uint feeMake_) {
        if (msg.sender != admin) throw;
        if (feeMake_ > feeMake) throw;
        feeMake = feeMake_;
      }
    
      function changeFeeTake(uint feeTake_) {
        if (msg.sender != admin) throw;
        if (feeTake_ > feeTake || feeTake_ < feeRebate) throw;
        feeTake = feeTake_;
      }
    
      function changeFeeRebate(uint feeRebate_) {
        if (msg.sender != admin) throw;
        if (feeRebate_ < feeRebate || feeRebate_ > feeTake) throw;
        feeRebate = feeRebate_;
      }
    
      function deposit() payable {
        tokens[0][msg.sender] = safeAdd(tokens[0][msg.sender], msg.value);
        Deposit(0, msg.sender, msg.value, tokens[0][msg.sender]);
      }
    
      function withdraw(uint amount) {
        if (tokens[0][msg.sender] < amount) throw;
        tokens[0][msg.sender] = safeSub(tokens[0][msg.sender], amount);
        if (!msg.sender.call.value(amount)()) throw;
        Withdraw(0, msg.sender, amount, tokens[0][msg.sender]);
      }
    
      function depositToken(address token, uint amount) {
        //remember to call Token(address).approve(this, amount) or this contract will not be able to do the transfer on your behalf.
        if (token==0) throw;
        if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
        tokens[token][msg.sender] = safeAdd(tokens[token][msg.sender], amount);
        Deposit(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function withdrawToken(address token, uint amount) {
        if (token==0) throw;
        if (tokens[token][msg.sender] < amount) throw;
        tokens[token][msg.sender] = safeSub(tokens[token][msg.sender], amount);
        if (!Token(token).transfer(msg.sender, amount)) throw;
        Withdraw(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function balanceOf(address token, address user) constant returns (uint) {
        return tokens[token][user];
      }
    
      function order(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce) {
        bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
        orders[msg.sender][hash] = true;
        Order(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, msg.sender);
      }
    
      function trade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s, uint amount) {
        //amount is in amountGet terms
        bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
        if (!(
          (orders[user][hash] || ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash),v,r,s) == user) &&
          block.number <= expires &&
          safeAdd(orderFills[user][hash], amount) <= amountGet
        )) throw;
        tradeBalances(tokenGet, amountGet, tokenGive, amountGive, user, amount);
        orderFills[user][hash] = safeAdd(orderFills[user][hash], amount);
        Trade(tokenGet, amount, tokenGive, amountGive * amount / amountGet, user, msg.sender);
      }
    
      function tradeBalances(address tokenGet, uint amountGet, address tokenGive, uint amountGive, address user, uint amount) private {
        uint feeMakeXfer = safeMul(amount, feeMake) / (1 ether);
        uint feeTakeXfer = safeMul(amount, feeTake) / (1 ether);
        uint feeRebateXfer = 0;
        if (accountLevelsAddr != 0x0) {
          uint accountLevel = AccountLevels(accountLevelsAddr).accountLevel(user);
          if (accountLevel==1) feeRebateXfer = safeMul(amount, feeRebate) / (1 ether);
          if (accountLevel==2) feeRebateXfer = feeTakeXfer;
        }
        tokens[tokenGet][msg.sender] = safeSub(tokens[tokenGet][msg.sender], safeAdd(amount, feeTakeXfer));
        tokens[tokenGet][user] = safeAdd(tokens[tokenGet][user], safeSub(safeAdd(amount, feeRebateXfer), feeMakeXfer));
        tokens[tokenGet][feeAccount] = safeAdd(tokens[tokenGet][feeAccount], safeSub(safeAdd(feeMakeXfer, feeTakeXfer), feeRebateXfer));
        tokens[tokenGive][user] = safeSub(tokens[tokenGive][user], safeMul(amountGive, amount) / amountGet);
        tokens[tokenGive][msg.sender] = safeAdd(tokens[tokenGive][msg.sender], safeMul(amountGive, amount) / amountGet);
      }
    
      function testTrade(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s, uint amount, address sender) constant returns(bool) {
        if (!(
          tokens[tokenGet][sender] >= amount &&
          availableVolume(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, user, v, r, s) >= amount
        )) return false;
        return true;
      }
    
      function availableVolume(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s) constant returns(uint) {
        bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
        if (!(
          (orders[user][hash] || ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash),v,r,s) == user) &&
          block.number <= expires
        )) return 0;
        uint available1 = safeSub(amountGet, orderFills[user][hash]);
        uint available2 = safeMul(tokens[tokenGive][user], amountGet) / amountGive;
        if (available1<available2) return available1;
        return available2;
      }
    
      function amountFilled(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s) constant returns(uint) {
        bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
        return orderFills[user][hash];
      }
    
      function cancelOrder(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, uint8 v, bytes32 r, bytes32 s) {
        bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
        if (!(orders[msg.sender][hash] || ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash),v,r,s) == msg.sender)) throw;
        orderFills[msg.sender][hash] = amountGet;
        Cancel(tokenGet, amountGet, tokenGive, amountGive, expires, nonce, msg.sender, v, r, s);
      }
    }

    File 2 of 2: PIXToken
    pragma solidity ^0.4.13;
    
    /**
     * Overflow aware uint math functions.
     *
     * Inspired by https://github.com/MakerDAO/maker-otc/blob/master/contracts/simple_market.sol
     */
    contract SafeMath {
        //internals
    
        function safeMul(uint a, uint b) internal returns (uint) {
            uint c = a * b;
            require(a == 0 || c / a == b);
            return c;
        }
    
        function safeSub(uint a, uint b) internal returns (uint) {
            require(b <= a);
            return a - b;
        }
    
        function safeAdd(uint a, uint b) internal returns (uint) {
            uint c = a + b;
            require(c>=a && c>=b);
            return c;
        }
    
        function safeDiv(uint a, uint b) internal returns (uint) {
            require(b > 0);
            uint c = a / b;
            require(a == b * c + a % b);
            return c;
        }
    }
    
    
    /**
     * ERC 20 token
     *
     * https://github.com/ethereum/EIPs/issues/20
     */
    interface Token {
    
        /// @param _owner The address from which the balance will be retrieved
        /// @return The balance
        function balanceOf(address _owner) constant returns (uint256 balance);
    
        /// @notice send `_value` token to `_to` from `msg.sender`
        /// @param _to The address of the recipient
        /// @param _value The amount of token to be transferred
        /// @return Whether the transfer was successful or not
        function transfer(address _to, uint256 _value) returns (bool success);
    
        /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
        /// @param _from The address of the sender
        /// @param _to The address of the recipient
        /// @param _value The amount of token to be transferred
        /// @return Whether the transfer was successful or not
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    
        /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
        /// @param _spender The address of the account able to transfer the tokens
        /// @param _value The amount of wei to be approved for transfer
        /// @return Whether the approval was successful or not
        function approve(address _spender, uint256 _value) returns (bool success);
    
        /// @param _owner The address of the account owning tokens
        /// @param _spender The address of the account able to transfer the tokens
        /// @return Amount of remaining tokens allowed to spent
        function allowance(address _owner, address _spender) constant returns (uint256 remaining);
    
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    }
    
    /**
     * ERC 20 token
     *
     * https://github.com/ethereum/EIPs/issues/20
     */
    contract StandardToken is Token {
    
        /**
         * Reviewed:
         * - Integer overflow = OK, checked
         */
        function transfer(address _to, uint256 _value) returns (bool success) {
            //Default assumes totalSupply can't be over max (2^256 - 1).
            //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
            //Replace the if with this one instead.
            if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
                //if (balances[msg.sender] >= _value && _value > 0) {
                balances[msg.sender] -= _value;
                balances[_to] += _value;
                Transfer(msg.sender, _to, _value);
                return true;
            } else { return false; }
        }
    
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
            //same as above. Replace this line with the following if you want to protect against wrapping uints.
            if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
                //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
                balances[_to] += _value;
                balances[_from] -= _value;
                allowed[_from][msg.sender] -= _value;
                Transfer(_from, _to, _value);
                return true;
            } else { return false; }
        }
    
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
    
        function approve(address _spender, uint256 _value) returns (bool success) {
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
    
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
            return allowed[_owner][_spender];
        }
    
        mapping(address => uint256) balances;
    
        mapping (address => mapping (address => uint256)) allowed;
    
        uint256 public totalSupply;
    }
    
    
    /**
     * PIX crowdsale ICO contract.
     *
     * Security criteria evaluated against http://ethereum.stackexchange.com/questions/8551/methodological-security-review-of-a-smart-contract
     *
     *
     */
    contract PIXToken is StandardToken, SafeMath {
    
        string public name = "PIX Token";
        string public symbol = "PIX";
    
        // Initial founder address (set in constructor)
        // This address is used as a controller address, in order to properly handle administration of the token.
        address public founder = 0x0;
    
        // Deposit Address - The funds will be sent here immediately after payments are made to the contract
        address public deposit = 0x0;
    
        /*
        Multi-stage sale contract.
    
        Notes:
        All token sales are tied to USD.  No token sales are for a fixed amount of Wei, this can shift and change over time.
        Due to this, the following needs to be paid attention to:
        1. The value of the token fluctuates in reference to the centsPerEth set on the contract.
        2. The tokens are priced in cents.  So all token purchases will be calculated out live at that time.
    
        Funding Stages:
        1. Pre-Sale, there will be 15M USD ( 125M tokens ) for sale. Bonus of 20%
        2. Day 1 sale, there will be 20M USD - the pre-sale amount of tokens for sale. (~166.6m tokens - Pre-Sale tokens) Bonus of 15%
        3. Day 2 sale, there will be 20M USD (~166.6m tokens) tokens for sale.  Bonus of 10%
        4. Days 3-10 sale, there will be 20M USD (~166.6m tokens) tokens for sale.  Bonus of 5%
    
        Post-Sale:
        1. 30% of the total token count is reserved for release every year, at 1/4th of the originally reserved value per year.
        2. 20% of the total token count [Minus the number of excess bonus tokens from the pre-sale] is issued out to the team when the sale has completed.
        3. Purchased tokens come available to be withdrawn 31 days after the sale has completed.
        */
    
        enum State { PreSale, Day1, Day2, Day3, Running, Halted } // the states through which this contract goes
        State state;
    
        // Pricing for the pre-sale in US Cents.
        uint public capPreSale = 15 * 10**8;  // 15M USD cap for pre-sale, this subtracts from day1 cap
        uint public capDay1 = 20 * 10**8;  // 20M USD cap for day 1
        uint public capDay2 = 20 * 10**8;  // 20M USD cap for day 2
        uint public capDay3 = 20 * 10**8;  // 20M USD cap for day 3 - 10
    
        // Token pricing information
        uint public weiPerEther = 10**18;
        uint public centsPerEth = 23000;
        uint public centsPerToken = 12;
    
        // Amount of funds raised in stages of pre-sale
        uint public raisePreSale = 0;  // USD raise during the pre-sale period
        uint public raiseDay1 = 0;  // USD raised on Day 1
        uint public raiseDay2 = 0;  // USD raised on Day 2
        uint public raiseDay3 = 0;  // USD raised during days 3-10
    
        // Block timing/contract unlocking information
        uint public publicSaleStart = 1502280000; // Aug 9, 2017 Noon UTC
        uint public day2Start = 1502366400; // Aug 10, 2017 Noon UTC
        uint public day3Start = 1502452800; // Aug 11, 2017 Noon UTC
        uint public saleEnd = 1503144000; // Aug 19, 2017 Noon UTC
        uint public coinTradeStart = 1505822400; // Sep 19, 2017 Noon UTC
        uint public year1Unlock = 1534680000; // Aug 19, 2018 Noon UTC
        uint public year2Unlock = 1566216000; // Aug 19, 2019 Noon UTC
        uint public year3Unlock = 1597838400; // Aug 19, 2020 Noon UTC
        uint public year4Unlock = 1629374400; // Aug 19, 2021 Noon UTC
    
        // Have the post-reward allocations been completed
        bool public allocatedFounders = false;
        bool public allocated1Year = false;
        bool public allocated2Year = false;
        bool public allocated3Year = false;
        bool public allocated4Year = false;
    
        // Token count information
        uint public totalTokensSale = 500000000; //total number of tokens being sold in the ICO, excluding bonuses, reserve, and team distributions
        uint public totalTokensReserve = 330000000;
        uint public totalTokensCompany = 220000000;
    
        bool public halted = false; //the founder address can set this to true to halt the crowdsale due to emergency.
    
        mapping(address => uint256) presaleWhitelist; // Pre-sale Whitelist
    
        event Buy(address indexed sender, uint eth, uint fbt);
        event Withdraw(address indexed sender, address to, uint eth);
        event AllocateTokens(address indexed sender);
    
        function PIXToken(address depositAddress) {
            /*
                Initialize the contract with a sane set of owners
            */
            founder = msg.sender;  // Allocate the founder address as a usable address separate from deposit.
            deposit = depositAddress;  // Store the deposit address.
        }
    
        function setETHUSDRate(uint centsPerEthInput) public {
            /*
                Sets the current ETH/USD Exchange rate in cents.  This modifies the token price in Wei.
            */
            require(msg.sender == founder);
            centsPerEth = centsPerEthInput;
        }
    
        /*
            Gets the current state of the contract based on the block number involved in the current transaction.
        */
        function getCurrentState() constant public returns (State) {
    
            if(halted) return State.Halted;
            else if(block.timestamp < publicSaleStart) return State.PreSale;
            else if(block.timestamp > publicSaleStart && block.timestamp <= day2Start) return State.Day1;
            else if(block.timestamp > day2Start && block.timestamp <= day3Start) return State.Day2;
            else if(block.timestamp > day3Start && block.timestamp <= saleEnd) return State.Day3;
            else return State.Running;
        }
    
        /*
            Gets the current amount of bonus per purchase in percent.
        */
        function getCurrentBonusInPercent() constant public returns (uint) {
            State s = getCurrentState();
            if (s == State.Halted) revert();
            else if(s == State.PreSale) return 20;
            else if(s == State.Day1) return 15;
            else if(s == State.Day2) return 10;
            else if(s == State.Day3) return 5;
            else return 0;
        }
    
        /*
            Get the current price of the token in WEI.  This should be the weiPerEther/centsPerEth * centsPerToken
        */
        function getTokenPriceInWEI() constant public returns (uint){
            uint weiPerCent = safeDiv(weiPerEther, centsPerEth);
            return safeMul(weiPerCent, centsPerToken);
        }
    
        /*
            Entry point for purchasing for one's self.
        */
        function buy() payable public {
            buyRecipient(msg.sender);
        }
    
        /*
            Main purchasing function for the contract
            1. Should validate the current state, from the getCurrentState() function
            2. Should only allow the founder to order during the pre-sale
            3. Should correctly calculate the values to be paid out during different stages of the contract.
        */
        function buyRecipient(address recipient) payable public {
            State current_state = getCurrentState(); // Get the current state of the contract.
            uint usdCentsRaise = safeDiv(safeMul(msg.value, centsPerEth), weiPerEther); // Get the current number of cents raised by the payment.
    
            if(current_state == State.PreSale)
            {
                require (presaleWhitelist[msg.sender] > 0);
                raisePreSale = safeAdd(raisePreSale, usdCentsRaise); //add current raise to pre-sell amount
                require(raisePreSale < capPreSale && usdCentsRaise < presaleWhitelist[msg.sender]); //ensure pre-sale cap, 15m usd * 100 so we have cents
                presaleWhitelist[msg.sender] = presaleWhitelist[msg.sender] - usdCentsRaise; // Remove the amount purchased from the pre-sale permitted for that user
            }
            else if (current_state == State.Day1)
            {
                raiseDay1 = safeAdd(raiseDay1, usdCentsRaise); //add current raise to pre-sell amount
                require(raiseDay1 < (capDay1 - raisePreSale)); //ensure day 1 cap, which is lower by the amount we pre-sold
            }
            else if (current_state == State.Day2)
            {
                raiseDay2 = safeAdd(raiseDay2, usdCentsRaise); //add current raise to pre-sell amount
                require(raiseDay2 < capDay2); //ensure day 2 cap
            }
            else if (current_state == State.Day3)
            {
                raiseDay3 = safeAdd(raiseDay3, usdCentsRaise); //add current raise to pre-sell amount
                require(raiseDay3 < capDay3); //ensure day 3 cap
            }
            else revert();
    
            uint tokens = safeDiv(msg.value, getTokenPriceInWEI()); // Calculate number of tokens to be paid out
            uint bonus = safeDiv(safeMul(tokens, getCurrentBonusInPercent()), 100); // Calculate number of bonus tokens
    
            if (current_state == State.PreSale) {
                // Remove the extra 5% from the totalTokensCompany, in order to keep the 550m on track.
                totalTokensCompany = safeSub(totalTokensCompany, safeDiv(bonus, 4));
            }
    
            uint totalTokens = safeAdd(tokens, bonus);
    
            balances[recipient] = safeAdd(balances[recipient], totalTokens);
            totalSupply = safeAdd(totalSupply, totalTokens);
    
            deposit.transfer(msg.value); // Send deposited Ether to the deposit address on file.
    
            Buy(recipient, msg.value, totalTokens);
        }
    
        /*
            Allocate reserved and founders tokens based on the running time and state of the contract.
         */
        function allocateReserveAndFounderTokens() {
            require(msg.sender==founder);
            require(getCurrentState() == State.Running);
            uint tokens = 0;
    
            if(block.timestamp > saleEnd && !allocatedFounders)
            {
                allocatedFounders = true;
                tokens = totalTokensCompany;
                balances[founder] = safeAdd(balances[founder], tokens);
                totalSupply = safeAdd(totalSupply, tokens);
            }
            else if(block.timestamp > year1Unlock && !allocated1Year)
            {
                allocated1Year = true;
                tokens = safeDiv(totalTokensReserve, 4);
                balances[founder] = safeAdd(balances[founder], tokens);
                totalSupply = safeAdd(totalSupply, tokens);
            }
            else if(block.timestamp > year2Unlock && !allocated2Year)
            {
                allocated2Year = true;
                tokens = safeDiv(totalTokensReserve, 4);
                balances[founder] = safeAdd(balances[founder], tokens);
                totalSupply = safeAdd(totalSupply, tokens);
            }
            else if(block.timestamp > year3Unlock && !allocated3Year)
            {
                allocated3Year = true;
                tokens = safeDiv(totalTokensReserve, 4);
                balances[founder] = safeAdd(balances[founder], tokens);
                totalSupply = safeAdd(totalSupply, tokens);
            }
            else if(block.timestamp > year4Unlock && !allocated4Year)
            {
                allocated4Year = true;
                tokens = safeDiv(totalTokensReserve, 4);
                balances[founder] = safeAdd(balances[founder], tokens);
                totalSupply = safeAdd(totalSupply, tokens);
            }
            else revert();
    
            AllocateTokens(msg.sender);
        }
    
        /**
         * Emergency Stop ICO.
         *
         *  Applicable tests:
         *
         * - Test unhalting, buying, and succeeding
         */
        function halt() {
            require(msg.sender==founder);
            halted = true;
        }
    
        function unhalt() {
            require(msg.sender==founder);
            halted = false;
        }
    
        /*
            Change founder address (Controlling address for contract)
        */
        function changeFounder(address newFounder) {
            require(msg.sender==founder);
            founder = newFounder;
        }
    
        /*
            Change deposit address (Address to which funds are deposited)
        */
        function changeDeposit(address newDeposit) {
            require(msg.sender==founder);
            deposit = newDeposit;
        }
    
        /*
            Add people to the pre-sale whitelist
            Amount should be the value in USD that the purchaser is allowed to buy
            IE: 100 is $100 is 10000 cents.  The correct value to enter is 100
        */
        function addPresaleWhitelist(address toWhitelist, uint256 amount){
            require(msg.sender==founder && amount > 0);
            presaleWhitelist[toWhitelist] = amount * 100;
        }
    
        /**
         * ERC 20 Standard Token interface transfer function
         *
         * Prevent transfers until freeze period is over.
         *
         * Applicable tests:
         *
         * - Test restricted early transfer
         * - Test transfer after restricted period
         */
        function transfer(address _to, uint256 _value) returns (bool success) {
            require(block.timestamp > coinTradeStart);
            return super.transfer(_to, _value);
        }
        /**
         * ERC 20 Standard Token interface transfer function
         *
         * Prevent transfers until freeze period is over.
         */
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
            require(block.timestamp > coinTradeStart);
            return super.transferFrom(_from, _to, _value);
        }
    
        function() payable {
            buyRecipient(msg.sender);
        }
    
    }