ETH Price: $2,541.28 (+1.02%)
Gas: 6.43 Gwei

Transaction Decoder

Block:
7362667 at Mar-13-2019 07:53:56 PM +UTC
Transaction Fee:
0.000191019 ETH $0.49
Gas Used:
63,673 Gas / 3 Gwei

Emitted Events:

36 CrowdsaleToken.Transfer( from=[Receiver] TokenStore, to=[Sender] 0x343a3c7f789335c9ea60932d34be258f643678d9, value=10753700000000000000 )
37 TokenStore.Withdraw( token=CrowdsaleToken, user=[Sender] 0x343a3c7f789335c9ea60932d34be258f643678d9, amount=10753700000000000000, balance=38783649052841 )

Account State Difference:

  Address   Before After State Difference Code
0x0Cf0Ee63...E122cC023
0x1cE7AE55...ee6Ee33D8
(Token.Store)
0x343a3C7F...F643678d9
0.42390716 Eth
Nonce: 22
0.423716141 Eth
Nonce: 23
0.000191019
(BTC.com Pool)
269.809674248641468852 Eth269.809865267641468852 Eth0.000191019

Execution Trace

TokenStore.withdrawToken( _token=0x0Cf0Ee63788A0849fE5297F3407f701E122cC023, _amount=10753700000000000000 )
  • CrowdsaleToken.transfer( _to=0x343a3C7F789335C9EA60932D34bE258F643678d9, _value=10753700000000000000 ) => ( success=True )
    File 1 of 2: TokenStore
    pragma solidity ^0.4.11;
    
    // ERC20 token protocol, see more details at
    // https://theethereum.wiki/w/index.php/ERC20_Token_Standard
    // And also https://github.com/ethereum/eips/issues/20
    
    contract Token {
      function totalSupply() constant returns (uint256 supply);
      function balanceOf(address _owner) constant returns (uint256 balance);
      function transfer(address _to, uint256 _value) returns (bool success);
      function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
      function approve(address _spender, uint256 _value) returns (bool success);
      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);
    }
    
    // Safe mathematics to make the code more readable
    
    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;
      }
    }
    
    // Ownable interface to simplify owner checks
    
    contract Ownable {
      address public owner;
    
      function Ownable() {
        owner = msg.sender;
      }
    
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
      function transferOwnership(address _newOwner) onlyOwner {
        require(_newOwner != address(0));
        owner = _newOwner;
      }
    }
    
    // Interface for trading discounts and rebates for specific accounts
    
    contract AccountModifiersInterface {
      function accountModifiers(address _user) constant returns(uint takeFeeDiscount, uint rebatePercentage);
      function tradeModifiers(address _maker, address _taker) constant returns(uint takeFeeDiscount, uint rebatePercentage);
    }
    
    // Interface for trade tacker
    
    contract TradeTrackerInterface {
      function tradeComplete(address _tokenGet, uint _amountGet, address _tokenGive, uint _amountGive, address _get, address _give, uint _takerFee, uint _makerRebate);
    }
    
    // Exchange contract
    
    contract TokenStore is SafeMath, Ownable {
    
      // The account that will receive fees
      address feeAccount;
    
      // The account that stores fee discounts/rebates
      address accountModifiers;
      
      // Trade tracker account
      address tradeTracker;
    
      // We charge only the takers and this is the fee, percentage times 1 ether
      uint public fee;
    
      // Mapping of token addresses to mapping of account balances (token 0 means Ether)
      mapping (address => mapping (address => uint)) public tokens;
    
      // Mapping of user accounts to mapping of order hashes to uints (amount of order that has been filled)
      mapping (address => mapping (bytes32 => uint)) public orderFills;
      
      // Address of a next and previous versions of the contract, also status of the contract
      // can be used for user-triggered fund migrations
      address public successor;
      address public predecessor;
      bool public deprecated;
      uint16 public version;
    
      // Logging events
      // Note: Order creation is handled off-chain, see explanation further below
      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, uint nonce);
      event Deposit(address token, address user, uint amount, uint balance);
      event Withdraw(address token, address user, uint amount, uint balance);
      event FundsMigrated(address user);
    
      function TokenStore(uint _fee, address _predecessor) {
        feeAccount = owner;
        fee = _fee;
        predecessor = _predecessor;
        deprecated = false;
        if (predecessor != address(0)) {
          version = TokenStore(predecessor).version() + 1;
        } else {
          version = 1;
        }
      }
    
      // Throw on default handler to prevent direct transactions of Ether
      function() {
        revert();
      }
      
      modifier deprecable() {
        require(!deprecated);
        _;
      }
    
      function deprecate(bool _deprecated, address _successor) onlyOwner {
        deprecated = _deprecated;
        successor = _successor;
      }
    
      function changeFeeAccount(address _feeAccount) onlyOwner {
        require(_feeAccount != address(0));
        feeAccount = _feeAccount;
      }
    
      function changeAccountModifiers(address _accountModifiers) onlyOwner {
        accountModifiers = _accountModifiers;
      }
      
      function changeTradeTracker(address _tradeTracker) onlyOwner {
        tradeTracker = _tradeTracker;
      }
    
      // Fee can only be decreased!
      function changeFee(uint _fee) onlyOwner {
        require(_fee <= fee);
        fee = _fee;
      }
      
      // Allows a user to get her current discount/rebate
      function getAccountModifiers() constant returns(uint takeFeeDiscount, uint rebatePercentage) {
        if (accountModifiers != address(0)) {
          return AccountModifiersInterface(accountModifiers).accountModifiers(msg.sender);
        } else {
          return (0, 0);
        }
      }
      
      ////////////////////////////////////////////////////////////////////////////////
      // Deposits, withdrawals, balances
      ////////////////////////////////////////////////////////////////////////////////
    
      function deposit() payable deprecable {
        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) {
        require(tokens[0][msg.sender] >= _amount);
        tokens[0][msg.sender] = safeSub(tokens[0][msg.sender], _amount);
        if (!msg.sender.call.value(_amount)()) {
          revert();
        }
        Withdraw(0, msg.sender, _amount, tokens[0][msg.sender]);
      }
    
      function depositToken(address _token, uint _amount) deprecable {
        // Note that Token(_token).approve(this, _amount) needs to be called
        // first or this contract will not be able to do the transfer.
        require(_token != 0);
        if (!Token(_token).transferFrom(msg.sender, this, _amount)) {
          revert();
        }
        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) {
        require(_token != 0);
        require(tokens[_token][msg.sender] >= _amount);
        tokens[_token][msg.sender] = safeSub(tokens[_token][msg.sender], _amount);
        if (!Token(_token).transfer(msg.sender, _amount)) {
          revert();
        }
        Withdraw(_token, msg.sender, _amount, tokens[_token][msg.sender]);
      }
    
      function balanceOf(address _token, address _user) constant returns (uint) {
        return tokens[_token][_user];
      }
      
      ////////////////////////////////////////////////////////////////////////////////
      // Trading
      ////////////////////////////////////////////////////////////////////////////////
    
      // Note: Order creation happens off-chain but the orders are signed by creators,
      // we validate the contents and the creator address in the logic below
    
      function trade(address _tokenGet, uint _amountGet, address _tokenGive, uint _amountGive,
          uint _expires, uint _nonce, address _user, uint8 _v, bytes32 _r, bytes32 _s, uint _amount) {
        bytes32 hash = sha256(this, _tokenGet, _amountGet, _tokenGive, _amountGive, _expires, _nonce);
        // Check order signatures and expiration, also check if not fulfilled yet
    		if (ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash), _v, _r, _s) != _user ||
          block.number > _expires ||
          safeAdd(orderFills[_user][hash], _amount) > _amountGet) {
          revert();
        }
        tradeBalances(_tokenGet, _amountGet, _tokenGive, _amountGive, _user, msg.sender, _amount);
        orderFills[_user][hash] = safeAdd(orderFills[_user][hash], _amount);
        Trade(_tokenGet, _amount, _tokenGive, _amountGive * _amount / _amountGet, _user, msg.sender, _nonce);
      }
      
      function tradeBalances(address _tokenGet, uint _amountGet, address _tokenGive, uint _amountGive,
          address _user, address _caller, uint _amount) private {
    
        uint feeTakeValue = safeMul(_amount, fee) / (1 ether);
        uint rebateValue = 0;
        uint tokenGiveValue = safeMul(_amountGive, _amount) / _amountGet; // Proportionate to request ratio
    
        // Apply modifiers
        if (accountModifiers != address(0)) {
          var (feeTakeDiscount, rebatePercentage) = AccountModifiersInterface(accountModifiers).tradeModifiers(_user, _caller);
          // Check that the discounts/rebates are never higher then 100%
          if (feeTakeDiscount > 100) {
            feeTakeDiscount = 0;
          }
          if (rebatePercentage > 100) {
            rebatePercentage = 0;
          }
          feeTakeValue = safeMul(feeTakeValue, 100 - feeTakeDiscount) / 100;  // discounted fee
          rebateValue = safeMul(rebatePercentage, feeTakeValue) / 100;        // % of actual taker fee
        }
        
        tokens[_tokenGet][_user] = safeAdd(tokens[_tokenGet][_user], safeAdd(_amount, rebateValue));
        tokens[_tokenGet][_caller] = safeSub(tokens[_tokenGet][_caller], safeAdd(_amount, feeTakeValue));
        tokens[_tokenGive][_user] = safeSub(tokens[_tokenGive][_user], tokenGiveValue);
        tokens[_tokenGive][_caller] = safeAdd(tokens[_tokenGive][_caller], tokenGiveValue);
        tokens[_tokenGet][feeAccount] = safeAdd(tokens[_tokenGet][feeAccount], safeSub(feeTakeValue, rebateValue));
        
        if (tradeTracker != address(0)) {
          TradeTrackerInterface(tradeTracker).tradeComplete(_tokenGet, _amount, _tokenGive, tokenGiveValue, _user, _caller, feeTakeValue, rebateValue);
        }
      }
    
      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 (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) 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 (!(ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash), _v, _r, _s) == msg.sender)) {
          revert();
        }
        orderFills[msg.sender][hash] = _amountGet;
        Cancel(_tokenGet, _amountGet, _tokenGive, _amountGive, _expires, _nonce, msg.sender, _v, _r, _s);
      }
      
      ////////////////////////////////////////////////////////////////////////////////
      // Migrations
      ////////////////////////////////////////////////////////////////////////////////
    
      // User-triggered (!) fund migrations in case contract got updated
      // Similar to withdraw but we use a successor account instead
      // As we don't store user tokens list on chain, it has to be passed from the outside
      function migrateFunds(address[] _tokens) {
      
        // Get the latest successor in the chain
        require(successor != address(0));
        TokenStore newExchange = TokenStore(successor);
        for (uint16 n = 0; n < 20; n++) {  // We will look past 20 contracts in the future
          address nextSuccessor = newExchange.successor();
          if (nextSuccessor == address(this)) {  // Circular succession
            revert();
          }
          if (nextSuccessor == address(0)) { // We reached the newest, stop
            break;
          }
          newExchange = TokenStore(nextSuccessor);
        }
    
        // Ether
        uint etherAmount = tokens[0][msg.sender];
        if (etherAmount > 0) {
          tokens[0][msg.sender] = 0;
          newExchange.depositForUser.value(etherAmount)(msg.sender);
        }
    
        // Tokens
        for (n = 0; n < _tokens.length; n++) {
          address token = _tokens[n];
          require(token != address(0)); // 0 = Ether, we handle it above
          uint tokenAmount = tokens[token][msg.sender];
          if (tokenAmount == 0) {
            continue;
          }
          if (!Token(token).approve(newExchange, tokenAmount)) {
            revert();
          }
          tokens[token][msg.sender] = 0;
          newExchange.depositTokenForUser(token, tokenAmount, msg.sender);
        }
    
        FundsMigrated(msg.sender);
      }
    
      // This is used for migrations only. To be called by previous exchange only,
      // user-triggered, on behalf of the user called the migrateFunds method.
      // Note that it does exactly the same as depositToken, but as this is called
      // by a previous generation of exchange itself, we credit internally not the
      // previous exchange, but the user it was called for.
      function depositForUser(address _user) payable deprecable {
        require(_user != address(0));
        require(msg.value > 0);
        TokenStore caller = TokenStore(msg.sender);
        require(caller.version() > 0); // Make sure it's an exchange account
        tokens[0][_user] = safeAdd(tokens[0][_user], msg.value);
      }
    
      function depositTokenForUser(address _token, uint _amount, address _user) deprecable {
        require(_token != address(0));
        require(_user != address(0));
        require(_amount > 0);
        TokenStore caller = TokenStore(msg.sender);
        require(caller.version() > 0); // Make sure it's an exchange account
        if (!Token(_token).transferFrom(msg.sender, this, _amount)) {
          revert();
        }
        tokens[_token][_user] = safeAdd(tokens[_token][_user], _amount);
      }
    }

    File 2 of 2: CrowdsaleToken
    /*
     * ERC20 interface
     * see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20 {
      uint public totalSupply;
      function balanceOf(address who) constant returns (uint);
      function allowance(address owner, address spender) constant returns (uint);
    
      function transfer(address to, uint value) returns (bool ok);
      function transferFrom(address from, address to, uint value) returns (bool ok);
      function approve(address spender, uint value) returns (bool ok);
      event Transfer(address indexed from, address indexed to, uint value);
      event Approval(address indexed owner, address indexed spender, uint value);
    }
    
    
    
    /**
     * Math operations with safety checks
     */
    contract SafeMath {
      function safeMul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeDiv(uint a, uint b) internal returns (uint) {
        assert(b > 0);
        uint c = a / b;
        assert(a == b * 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 max64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a >= b ? a : b;
      }
    
      function min64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a < b ? a : b;
      }
    
      function max256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a >= b ? a : b;
      }
    
      function min256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a < b ? a : b;
      }
    
      function assert(bool assertion) internal {
        if (!assertion) {
          throw;
        }
      }
    }
    
    
    
    /**
     * Standard ERC20 token with Short Hand Attack and approve() race condition mitigation.
     *
     * Based on code by FirstBlood:
     * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
     */
    contract StandardToken is ERC20, SafeMath {
    
      /* Token supply got increased and a new owner received these tokens */
      event Minted(address receiver, uint amount);
    
      /* Actual balances of token holders */
      mapping(address => uint) balances;
    
      /* approve() allowances */
      mapping (address => mapping (address => uint)) allowed;
    
      /* Interface declaration */
      function isToken() public constant returns (bool weAre) {
        return true;
      }
    
      function transfer(address _to, uint _value) returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], _value);
        balances[_to] = safeAdd(balances[_to], _value);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      function transferFrom(address _from, address _to, uint _value) returns (bool success) {
        uint _allowance = allowed[_from][msg.sender];
    
        balances[_to] = safeAdd(balances[_to], _value);
        balances[_from] = safeSub(balances[_from], _value);
        allowed[_from][msg.sender] = safeSub(_allowance, _value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      function balanceOf(address _owner) constant returns (uint balance) {
        return balances[_owner];
      }
    
      function approve(address _spender, uint _value) returns (bool success) {
    
        // To change the approve amount you first have to reduce the addresses`
        //  allowance to zero by calling `approve(_spender, 0)` if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
    
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      function allowance(address _owner, address _spender) constant returns (uint remaining) {
        return allowed[_owner][_spender];
      }
    
    }
    
    
    
    
    
    /**
     * Upgrade agent interface inspired by Lunyr.
     *
     * Upgrade agent transfers tokens to a new contract.
     * Upgrade agent itself can be the token contract, or just a middle man contract doing the heavy lifting.
     */
    contract UpgradeAgent {
    
      uint public originalSupply;
    
      /** Interface marker */
      function isUpgradeAgent() public constant returns (bool) {
        return true;
      }
    
      function upgradeFrom(address _from, uint256 _value) public;
    
    }
    
    
    /**
     * A token upgrade mechanism where users can opt-in amount of tokens to the next smart contract revision.
     *
     * First envisioned by Golem and Lunyr projects.
     */
    contract UpgradeableToken is StandardToken {
    
      /** Contract / person who can set the upgrade path. This can be the same as team multisig wallet, as what it is with its default value. */
      address public upgradeMaster;
    
      /** The next contract where the tokens will be migrated. */
      UpgradeAgent public upgradeAgent;
    
      /** How many tokens we have upgraded by now. */
      uint256 public totalUpgraded;
    
      /**
       * Upgrade states.
       *
       * - NotAllowed: The child contract has not reached a condition where the upgrade can bgun
       * - WaitingForAgent: Token allows upgrade, but we don't have a new agent yet
       * - ReadyToUpgrade: The agent is set, but not a single token has been upgraded yet
       * - Upgrading: Upgrade agent is set and the balance holders can upgrade their tokens
       *
       */
      enum UpgradeState {Unknown, NotAllowed, WaitingForAgent, ReadyToUpgrade, Upgrading}
    
      /**
       * Somebody has upgraded some of his tokens.
       */
      event Upgrade(address indexed _from, address indexed _to, uint256 _value);
    
      /**
       * New upgrade agent available.
       */
      event UpgradeAgentSet(address agent);
    
      /**
       * Do not allow construction without upgrade master set.
       */
      function UpgradeableToken(address _upgradeMaster) {
        upgradeMaster = _upgradeMaster;
      }
    
      /**
       * Allow the token holder to upgrade some of their tokens to a new contract.
       */
      function upgrade(uint256 value) public {
    
          UpgradeState state = getUpgradeState();
          if(!(state == UpgradeState.ReadyToUpgrade || state == UpgradeState.Upgrading)) {
            // Called in a bad state
            throw;
          }
    
          // Validate input value.
          if (value == 0) throw;
    
          balances[msg.sender] = safeSub(balances[msg.sender], value);
    
          // Take tokens out from circulation
          totalSupply = safeSub(totalSupply, value);
          totalUpgraded = safeAdd(totalUpgraded, value);
    
          // Upgrade agent reissues the tokens
          upgradeAgent.upgradeFrom(msg.sender, value);
          Upgrade(msg.sender, upgradeAgent, value);
      }
    
      /**
       * Set an upgrade agent that handles
       */
      function setUpgradeAgent(address agent) external {
    
          if(!canUpgrade()) {
            // The token is not yet in a state that we could think upgrading
            throw;
          }
    
          if (agent == 0x0) throw;
          // Only a master can designate the next agent
          if (msg.sender != upgradeMaster) throw;
          // Upgrade has already begun for an agent
          if (getUpgradeState() == UpgradeState.Upgrading) throw;
    
          upgradeAgent = UpgradeAgent(agent);
    
          // Bad interface
          if(!upgradeAgent.isUpgradeAgent()) throw;
          // Make sure that token supplies match in source and target
          if (upgradeAgent.originalSupply() != totalSupply) throw;
    
          UpgradeAgentSet(upgradeAgent);
      }
    
      /**
       * Get the state of the token upgrade.
       */
      function getUpgradeState() public constant returns(UpgradeState) {
        if(!canUpgrade()) return UpgradeState.NotAllowed;
        else if(address(upgradeAgent) == 0x00) return UpgradeState.WaitingForAgent;
        else if(totalUpgraded == 0) return UpgradeState.ReadyToUpgrade;
        else return UpgradeState.Upgrading;
      }
    
      /**
       * Change the upgrade master.
       *
       * This allows us to set a new owner for the upgrade mechanism.
       */
      function setUpgradeMaster(address master) public {
          if (master == 0x0) throw;
          if (msg.sender != upgradeMaster) throw;
          upgradeMaster = master;
      }
    
      /**
       * Child contract can enable to provide the condition when the upgrade can begun.
       */
      function canUpgrade() public constant returns(bool) {
         return true;
      }
    
    }
    
    
    
    
    /*
     * Ownable
     *
     * Base contract with an owner.
     * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
     */
    contract Ownable {
      address public owner;
    
      function Ownable() {
        owner = msg.sender;
      }
    
      modifier onlyOwner() {
        if (msg.sender != owner) {
          throw;
        }
        _;
      }
    
      function transferOwnership(address newOwner) onlyOwner {
        if (newOwner != address(0)) {
          owner = newOwner;
        }
      }
    
    }
    
    
    
    
    /**
     * Define interface for releasing the token transfer after a successful crowdsale.
     */
    contract ReleasableToken is ERC20, Ownable {
    
      /* The finalizer contract that allows unlift the transfer limits on this token */
      address public releaseAgent;
    
      /** A crowdsale contract can release us to the wild if ICO success. If false we are are in transfer lock up period.*/
      bool public released = false;
    
      /** Map of agents that are allowed to transfer tokens regardless of the lock down period. These are crowdsale contracts and possible the team multisig itself. */
      mapping (address => bool) public transferAgents;
    
      /**
       * Limit token transfer until the crowdsale is over.
       *
       */
      modifier canTransfer(address _sender) {
    
        if(!released) {
            if(!transferAgents[_sender]) {
                throw;
            }
        }
    
        _;
      }
    
      /**
       * Set the contract that can call release and make the token transferable.
       *
       * Design choice. Allow reset the release agent to fix fat finger mistakes.
       */
      function setReleaseAgent(address addr) onlyOwner inReleaseState(false) public {
    
        // We don't do interface check here as we might want to a normal wallet address to act as a release agent
        releaseAgent = addr;
      }
    
      /**
       * Owner can allow a particular address (a crowdsale contract) to transfer tokens despite the lock up period.
       */
      function setTransferAgent(address addr, bool state) onlyOwner inReleaseState(false) public {
        transferAgents[addr] = state;
      }
    
      /**
       * One way function to release the tokens to the wild.
       *
       * Can be called only from the release agent that is the final ICO contract. It is only called if the crowdsale has been success (first milestone reached).
       */
      function releaseTokenTransfer() public onlyReleaseAgent {
        released = true;
      }
    
      /** The function can be called only before or after the tokens have been releasesd */
      modifier inReleaseState(bool releaseState) {
        if(releaseState != released) {
            throw;
        }
        _;
      }
    
      /** The function can be called only by a whitelisted release agent. */
      modifier onlyReleaseAgent() {
        if(msg.sender != releaseAgent) {
            throw;
        }
        _;
      }
    
      function transfer(address _to, uint _value) canTransfer(msg.sender) returns (bool success) {
        // Call StandardToken.transfer()
       return super.transfer(_to, _value);
      }
    
      function transferFrom(address _from, address _to, uint _value) canTransfer(_from) returns (bool success) {
        // Call StandardToken.transferForm()
        return super.transferFrom(_from, _to, _value);
      }
    
    }
    
    
    
    
    
    /**
     * Safe unsigned safe math.
     *
     * https://blog.aragon.one/library-driven-development-in-solidity-2bebcaf88736#.750gwtwli
     *
     * Originally from https://raw.githubusercontent.com/AragonOne/zeppelin-solidity/master/contracts/SafeMathLib.sol
     *
     * Maintained here until merged to mainline zeppelin-solidity.
     *
     */
    library SafeMathLib {
    
      function times(uint a, uint b) returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function minus(uint a, uint b) returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function plus(uint a, uint b) returns (uint) {
        uint c = a + b;
        assert(c>=a);
        return c;
      }
    
      function assert(bool assertion) private {
        if (!assertion) throw;
      }
    }
    
    
    
    /**
     * A token that can increase its supply by another contract.
     *
     * This allows uncapped crowdsale by dynamically increasing the supply when money pours in.
     * Only mint agents, contracts whitelisted by owner, can mint new tokens.
     *
     */
    contract MintableToken is StandardToken, Ownable {
    
      using SafeMathLib for uint;
    
      bool public mintingFinished = false;
    
      /** List of agents that are allowed to create new tokens */
      mapping (address => bool) public mintAgents;
    
      event MintingAgentChanged(address addr, bool state  );
    
      /**
       * Create new tokens and allocate them to an address..
       *
       * Only callably by a crowdsale contract (mint agent).
       */
      function mint(address receiver, uint amount) onlyMintAgent canMint public {
        totalSupply = totalSupply.plus(amount);
        balances[receiver] = balances[receiver].plus(amount);
    
        // This will make the mint transaction apper in EtherScan.io
        // We can remove this after there is a standardized minting event
        Transfer(0, receiver, amount);
      }
    
      /**
       * Owner can allow a crowdsale contract to mint new tokens.
       */
      function setMintAgent(address addr, bool state) onlyOwner canMint public {
        mintAgents[addr] = state;
        MintingAgentChanged(addr, state);
      }
    
      modifier onlyMintAgent() {
        // Only crowdsale contracts are allowed to mint new tokens
        if(!mintAgents[msg.sender]) {
            throw;
        }
        _;
      }
    
      /** Make sure we are not done yet. */
      modifier canMint() {
        if(mintingFinished) throw;
        _;
      }
    }
    
    
    
    /**
     * A crowdsaled token.
     *
     * An ERC-20 token designed specifically for crowdsales with investor protection and further development path.
     *
     * - The token transfer() is disabled until the crowdsale is over
     * - The token contract gives an opt-in upgrade path to a new contract
     * - The same token can be part of several crowdsales through approve() mechanism
     * - The token can be capped (supply set in the constructor) or uncapped (crowdsale contract can mint new tokens)
     *
     */
    contract CrowdsaleToken is ReleasableToken, MintableToken, UpgradeableToken {
    
      /** Name and symbol were updated. */
      event UpdatedTokenInformation(string newName, string newSymbol);
    
      string public name;
    
      string public symbol;
    
      uint public decimals;
    
      /**
       * Construct the token.
       *
       * This token must be created through a team multisig wallet, so that it is owned by that wallet.
       *
       * @param _name Token name
       * @param _symbol Token symbol - should be all caps
       * @param _initialSupply How many tokens we start with
       * @param _decimals Number of decimal places
       * @param _mintable Are new tokens created over the crowdsale or do we distribute only the initial supply? Note that when the token becomes transferable the minting always ends.
       */
      function CrowdsaleToken(string _name, string _symbol, uint _initialSupply, uint _decimals, bool _mintable)
        UpgradeableToken(msg.sender) {
    
        // Create any address, can be transferred
        // to team multisig via changeOwner(),
        // also remember to call setUpgradeMaster()
        owner = msg.sender;
    
        name = _name;
        symbol = _symbol;
    
        totalSupply = _initialSupply;
    
        decimals = _decimals;
    
        // Create initially all balance on the team multisig
        balances[owner] = totalSupply;
    
        if(totalSupply > 0) {
          Minted(owner, totalSupply);
        }
    
        // No more new supply allowed after the token creation
        if(!_mintable) {
          mintingFinished = true;
          if(totalSupply == 0) {
            throw; // Cannot create a token without supply and no minting
          }
        }
      }
    
      /**
       * When token is released to be transferable, enforce no new tokens can be created.
       */
      function releaseTokenTransfer() public onlyReleaseAgent {
        mintingFinished = true;
        super.releaseTokenTransfer();
      }
    
      /**
       * Allow upgrade agent functionality kick in only if the crowdsale was success.
       */
      function canUpgrade() public constant returns(bool) {
        return released && super.canUpgrade();
      }
    
      /**
       * Owner can update token information here.
       *
       * It is often useful to conceal the actual token association, until
       * the token operations, like central issuance or reissuance have been completed.
       *
       * This function allows the token owner to rename the token after the operations
       * have been completed and then point the audience to use the token contract.
       */
      function setTokenInformation(string _name, string _symbol) onlyOwner {
        name = _name;
        symbol = _symbol;
    
        UpdatedTokenInformation(name, symbol);
      }
    
    }