ETH Price: $1,815.16 (-4.49%)

Transaction Decoder

Block:
5539218 at May-01-2018 06:33:42 PM +UTC
Transaction Fee:
0.000216785 ETH $0.39
Gas Used:
43,357 Gas / 5 Gwei

Emitted Events:

31 NexoToken.Transfer( from=[Sender] 0x3fcd22ce2564b55016fb62149ee3a22ee20ecb97, to=[Receiver] Exchange, value=35296675333378273434463 )
32 Exchange.Deposit( token=NexoToken, user=[Sender] 0x3fcd22ce2564b55016fb62149ee3a22ee20ecb97, amount=35296675333378273434463, balance=35296675333378273434463 )

Account State Difference:

  Address   Before After State Difference Code
0x2a0c0DBE...44050c208
(IDEX)
0x3FCD22Ce...Ee20eCb97
0.080362302 Eth
Nonce: 96
0.080145517 Eth
Nonce: 97
0.000216785
(MiningPoolHub: Old Address)
26,194.597802248705910548 Eth26,194.598019033705910548 Eth0.000216785
0xB62132e3...d8d815206

Execution Trace

Exchange.depositToken( token=0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206, amount=35296675333378273434463 )
  • NexoToken.transferFrom( _from=0x3FCD22Ce2564B55016Fb62149ee3A22Ee20eCb97, _to=0x2a0c0DBEcC7E4D658f48E01e3fA353F44050c208, _value=35296675333378273434463 ) => ( success=True )
    File 1 of 2: Exchange
    pragma solidity ^0.4.16;
    
    contract Token {
        bytes32 public standard;
        bytes32 public name;
        bytes32 public symbol;
        uint256 public totalSupply;
        uint8 public decimals;
        bool public allowTransactions;
        mapping (address => uint256) public balanceOf;
        mapping (address => mapping (address => uint256)) public allowance;
        function transfer(address _to, uint256 _value) returns (bool success);
        function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success);
        function approve(address _spender, uint256 _value) returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    }
    
    contract Exchange {
      function assert(bool assertion) {
        if (!assertion) throw;
      }
      function safeMul(uint a, uint b) returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function safeSub(uint a, uint b) returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function safeAdd(uint a, uint b) returns (uint) {
        uint c = a + b;
        assert(c>=a && c>=b);
        return c;
      }
      address public owner;
      mapping (address => uint256) public invalidOrder;
      event SetOwner(address indexed previousOwner, address indexed newOwner);
      modifier onlyOwner {
        assert(msg.sender == owner);
        _;
      }
      function setOwner(address newOwner) onlyOwner {
        SetOwner(owner, newOwner);
        owner = newOwner;
      }
      function getOwner() returns (address out) {
        return owner;
      }
      function invalidateOrdersBefore(address user, uint256 nonce) onlyAdmin {
        if (nonce < invalidOrder[user]) throw;
        invalidOrder[user] = nonce;
      }
    
      mapping (address => mapping (address => uint256)) public tokens; //mapping of token addresses to mapping of account balances
    
      mapping (address => bool) public admins;
      mapping (address => uint256) public lastActiveTransaction;
      mapping (bytes32 => uint256) public orderFills;
      address public feeAccount;
      uint256 public inactivityReleasePeriod;
      mapping (bytes32 => bool) public traded;
      mapping (bytes32 => bool) public withdrawn;
      event Order(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
      event Cancel(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
      event Trade(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, address get, address give);
      event Deposit(address token, address user, uint256 amount, uint256 balance);
      event Withdraw(address token, address user, uint256 amount, uint256 balance);
    
      function setInactivityReleasePeriod(uint256 expiry) onlyAdmin returns (bool success) {
        if (expiry > 1000000) throw;
        inactivityReleasePeriod = expiry;
        return true;
      }
    
      function Exchange(address feeAccount_) {
        owner = msg.sender;
        feeAccount = feeAccount_;
        inactivityReleasePeriod = 100000;
      }
    
      function setAdmin(address admin, bool isAdmin) onlyOwner {
        admins[admin] = isAdmin;
      }
    
      modifier onlyAdmin {
        if (msg.sender != owner && !admins[msg.sender]) throw;
        _;
      }
    
      function() external {
        throw;
      }
    
      function depositToken(address token, uint256 amount) {
        tokens[token][msg.sender] = safeAdd(tokens[token][msg.sender], amount);
        lastActiveTransaction[msg.sender] = block.number;
        if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
        Deposit(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function deposit() payable {
        tokens[address(0)][msg.sender] = safeAdd(tokens[address(0)][msg.sender], msg.value);
        lastActiveTransaction[msg.sender] = block.number;
        Deposit(address(0), msg.sender, msg.value, tokens[address(0)][msg.sender]);
      }
    
      function withdraw(address token, uint256 amount) returns (bool success) {
        if (safeSub(block.number, lastActiveTransaction[msg.sender]) < inactivityReleasePeriod) throw;
        if (tokens[token][msg.sender] < amount) throw;
        tokens[token][msg.sender] = safeSub(tokens[token][msg.sender], amount);
        if (token == address(0)) {
          if (!msg.sender.send(amount)) throw;
        } else {
          if (!Token(token).transfer(msg.sender, amount)) throw;
        }
        Withdraw(token, msg.sender, amount, tokens[token][msg.sender]);
      }
    
      function adminWithdraw(address token, uint256 amount, address user, uint256 nonce, uint8 v, bytes32 r, bytes32 s, uint256 feeWithdrawal) onlyAdmin returns (bool success) {
        bytes32 hash = keccak256(this, token, amount, user, nonce);
        if (withdrawn[hash]) throw;
        withdrawn[hash] = true;
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", hash), v, r, s) != user) throw;
        if (feeWithdrawal > 50 finney) feeWithdrawal = 50 finney;
        if (tokens[token][user] < amount) throw;
        tokens[token][user] = safeSub(tokens[token][user], amount);
        tokens[token][feeAccount] = safeAdd(tokens[token][feeAccount], safeMul(feeWithdrawal, amount) / 1 ether);
        amount = safeMul((1 ether - feeWithdrawal), amount) / 1 ether;
        if (token == address(0)) {
          if (!user.send(amount)) throw;
        } else {
          if (!Token(token).transfer(user, amount)) throw;
        }
        lastActiveTransaction[user] = block.number;
        Withdraw(token, user, amount, tokens[token][user]);
      }
    
      function balanceOf(address token, address user) constant returns (uint256) {
        return tokens[token][user];
      }
    
      function trade(uint256[8] tradeValues, address[4] tradeAddresses, uint8[2] v, bytes32[4] rs) onlyAdmin returns (bool success) {
        /* amount is in amountBuy terms */
        /* tradeValues
           [0] amountBuy
           [1] amountSell
           [2] expires
           [3] nonce
           [4] amount
           [5] tradeNonce
           [6] feeMake
           [7] feeTake
         tradeAddressses
           [0] tokenBuy
           [1] tokenSell
           [2] maker
           [3] taker
         */
        if (invalidOrder[tradeAddresses[2]] > tradeValues[3]) throw;
        bytes32 orderHash = keccak256(this, tradeAddresses[0], tradeValues[0], tradeAddresses[1], tradeValues[1], tradeValues[2], tradeValues[3], tradeAddresses[2]);
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", orderHash), v[0], rs[0], rs[1]) != tradeAddresses[2]) throw;
        bytes32 tradeHash = keccak256(orderHash, tradeValues[4], tradeAddresses[3], tradeValues[5]); 
        if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", tradeHash), v[1], rs[2], rs[3]) != tradeAddresses[3]) throw;
        if (traded[tradeHash]) throw;
        traded[tradeHash] = true;
        if (tradeValues[6] > 100 finney) tradeValues[6] = 100 finney;
        if (tradeValues[7] > 100 finney) tradeValues[7] = 100 finney;
        if (safeAdd(orderFills[orderHash], tradeValues[4]) > tradeValues[0]) throw;
        if (tokens[tradeAddresses[0]][tradeAddresses[3]] < tradeValues[4]) throw;
        if (tokens[tradeAddresses[1]][tradeAddresses[2]] < (safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0])) throw;
        tokens[tradeAddresses[0]][tradeAddresses[3]] = safeSub(tokens[tradeAddresses[0]][tradeAddresses[3]], tradeValues[4]);
        tokens[tradeAddresses[0]][tradeAddresses[2]] = safeAdd(tokens[tradeAddresses[0]][tradeAddresses[2]], safeMul(tradeValues[4], ((1 ether) - tradeValues[6])) / (1 ether));
        tokens[tradeAddresses[0]][feeAccount] = safeAdd(tokens[tradeAddresses[0]][feeAccount], safeMul(tradeValues[4], tradeValues[6]) / (1 ether));
        tokens[tradeAddresses[1]][tradeAddresses[2]] = safeSub(tokens[tradeAddresses[1]][tradeAddresses[2]], safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0]);
        tokens[tradeAddresses[1]][tradeAddresses[3]] = safeAdd(tokens[tradeAddresses[1]][tradeAddresses[3]], safeMul(safeMul(((1 ether) - tradeValues[7]), tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
        tokens[tradeAddresses[1]][feeAccount] = safeAdd(tokens[tradeAddresses[1]][feeAccount], safeMul(safeMul(tradeValues[7], tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
        orderFills[orderHash] = safeAdd(orderFills[orderHash], tradeValues[4]);
        lastActiveTransaction[tradeAddresses[2]] = block.number;
        lastActiveTransaction[tradeAddresses[3]] = block.number;
      }
    }

    File 2 of 2: NexoToken
    pragma solidity 0.4.23;
    
    //
    // This source file is part of the current-contracts open source project
    // Copyright 2018 Zerion LLC
    // Licensed under Apache License v2.0
    //
    
    
    // @title Abstract ERC20 token interface
    contract AbstractToken {
    	function balanceOf(address owner) public view returns (uint256 balance);
    	function transfer(address to, uint256 value) public returns (bool success);
    	function transferFrom(address from, address to, uint256 value) public returns (bool success);
    	function approve(address spender, uint256 value) public returns (bool success);
    	function allowance(address owner, address spender) public view returns (uint256 remaining);
    
    	event Transfer(address indexed from, address indexed to, uint256 value);
    	event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    contract Owned {
    
    	address public owner = msg.sender;
    	address public potentialOwner;
    
    	modifier onlyOwner {
    		require(msg.sender == owner);
    		_;
    	}
    
    	modifier onlyPotentialOwner {
    		require(msg.sender == potentialOwner);
    		_;
    	}
    
    	event NewOwner(address old, address current);
    	event NewPotentialOwner(address old, address potential);
    
    	function setOwner(address _new)
    		public
    		onlyOwner
    	{
    		emit NewPotentialOwner(owner, _new);
    		potentialOwner = _new;
    	}
    
    	function confirmOwnership()
    		public
    		onlyPotentialOwner
    	{
    		emit NewOwner(owner, potentialOwner);
    		owner = potentialOwner;
    		potentialOwner = address(0);
    	}
    }
    
    // @title SafeMath contract - Math operations with safety checks.
    // @author OpenZeppelin: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol
    contract SafeMath {
    	/**
    	* @dev Multiplies two numbers, throws on overflow.
    	*/
    	function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    		if (a == 0) {
    			return 0;
    		}
    		uint256 c = a * b;
    		assert(c / a == b);
    		return c;
    	}
    
    	/**
    	* @dev Integer division of two numbers, truncating the quotient.
    	*/
    	function div(uint256 a, uint256 b) internal pure returns (uint256) {
    		return a / b;
    	}
    
    	/**
    	* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    	*/
    	function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    		assert(b <= a);
    		return a - b;
    	}
    
    	/**
    	* @dev Adds two numbers, throws on overflow.
    	*/
    	function add(uint256 a, uint256 b) internal pure returns (uint256) {
    		uint256 c = a + b;
    		assert(c >= a);
    		return c;
    	}
    
    	/**
    	* @dev Raises `a` to the `b`th power, throws on overflow.
    	*/
    	function pow(uint256 a, uint256 b) internal pure returns (uint256) {
    		uint256 c = a ** b;
    		assert(c >= a);
    		return c;
    	}
    }
    
    /// Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
    contract StandardToken is AbstractToken, Owned, SafeMath {
    
    	/*
    	 *  Data structures
    	 */
    	mapping (address => uint256) internal balances;
    	mapping (address => mapping (address => uint256)) internal allowed;
    	uint256 public totalSupply;
    
    	/*
    	 *  Read and write storage functions
    	 */
    	/// @dev Transfers sender's tokens to a given address. Returns success.
    	/// @param _to Address of token receiver.
    	/// @param _value Number of tokens to transfer.
    	function transfer(address _to, uint256 _value) public returns (bool success) {
    		return _transfer(msg.sender, _to, _value);
    	}
    
    	/// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.
    	/// @param _from Address from where tokens are withdrawn.
    	/// @param _to Address to where tokens are sent.
    	/// @param _value Number of tokens to transfer.
    	function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    		require(allowed[_from][msg.sender] >= _value);
    		allowed[_from][msg.sender] -= _value;
    
    		return _transfer(_from, _to, _value);
    	}
    
    	/// @dev Returns number of tokens owned by given address.
    	/// @param _owner Address of token owner.
    	function balanceOf(address _owner) public view returns (uint256 balance) {
    		return balances[_owner];
    	}
    
    	/// @dev Sets approved amount of tokens for spender. Returns success.
    	/// @param _spender Address of allowed account.
    	/// @param _value Number of approved tokens.
    	function approve(address _spender, uint256 _value) public returns (bool success) {
    		allowed[msg.sender][_spender] = _value;
    		emit Approval(msg.sender, _spender, _value);
    		return true;
    	}
    
    	/*
    	 * Read storage functions
    	 */
    	/// @dev Returns number of allowed tokens for given address.
    	/// @param _owner Address of token owner.
    	/// @param _spender Address of token spender.
    	function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
    		return allowed[_owner][_spender];
    	}
    
    	/**
    	* @dev Private transfer, can only be called by this contract.
    	* @param _from The address of the sender.
    	* @param _to The address of the recipient.
    	* @param _value The amount to send.
    	* @return success True if the transfer was successful, or throws.
    	*/
    	function _transfer(address _from, address _to, uint256 _value) private returns (bool success) {
    		require(_to != address(0));
    		require(balances[_from] >= _value);
    		balances[_from] -= _value;
    		balances[_to] = add(balances[_to], _value);
    		emit Transfer(_from, _to, _value);
    		return true;
    	}
    }
    
    /// @title Token contract - Implements Standard ERC20 with additional features.
    /// @author Zerion - <[email protected]>
    contract Token is StandardToken {
    
    	// Time of the contract creation
    	uint256 public creationTime;
    
    	function Token() public {
    		/* solium-disable-next-line security/no-block-members */
    		creationTime = now;
    	}
    
    	/// @dev Owner can transfer out any accidentally sent ERC20 tokens
    	function transferERC20Token(AbstractToken _token, address _to, uint256 _value)
    		public
    		onlyOwner
    		returns (bool success)
    	{
    		require(_token.balanceOf(address(this)) >= _value);
    		uint256 receiverBalance = _token.balanceOf(_to);
    		require(_token.transfer(_to, _value));
    
    		uint256 receiverNewBalance = _token.balanceOf(_to);
    		assert(receiverNewBalance == add(receiverBalance, _value));
    
    		return true;
    	}
    
    	/// @dev Increases approved amount of tokens for spender. Returns success.
    	function increaseApproval(address _spender, uint256 _value) public returns (bool success) {
    		allowed[msg.sender][_spender] = add(allowed[msg.sender][_spender], _value);
    		emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    		return true;
    	}
    
    	/// @dev Decreases approved amount of tokens for spender. Returns success.
    	function decreaseApproval(address _spender, uint256 _value) public returns (bool success) {
    		uint256 oldValue = allowed[msg.sender][_spender];
    		if (_value > oldValue) {
    			allowed[msg.sender][_spender] = 0;
    		} else {
    			allowed[msg.sender][_spender] = sub(oldValue, _value);
    		}
    		emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    		return true;
    	}
    }
    
    // @title Token contract - Implements Standard ERC20 Token for NEXO project.
    /// @author Zerion - <[email protected]>
    contract NexoToken is Token {
    
    	/// TOKEN META DATA
    	string constant public name = 'Nexo';
    	string constant public symbol = 'NEXO';
    	uint8  constant public decimals = 18;
    
    
    	/// ALOCATIONS
    	// To calculate vesting periods we assume that 1 month is always equal to 30 days 
    
    
    	/*** Initial Investors' tokens ***/
    
    	// 525,000,000 (52.50%) tokens are distributed among initial investors
    	// These tokens will be distributed without vesting
    
    	address public investorsAllocation = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF);
    	uint256 public investorsTotal = 525000000e18;
    
    
    	/*** Overdraft Reserves ***/
    
    	// 250,000,000 (25%) tokens will be eventually available for overdraft
    	// These tokens will be distributed monthly with a 6 month cliff within a year
    	// 41,666,666 tokens will be unlocked every month after the cliff
    	// 4 tokens will be unlocked without vesting to ensure that total amount sums up to 250,000,000.
    
    	address public overdraftAllocation = address(0x1111111111111111111111111111111111111111);
    	uint256 public overdraftTotal = 250000000e18;
    	uint256 public overdraftPeriodAmount = 41666666e18;
    	uint256 public overdraftUnvested = 4e18;
    	uint256 public overdraftCliff = 5 * 30 days;
    	uint256 public overdraftPeriodLength = 30 days;
    	uint8   public overdraftPeriodsNumber = 6;
    
    
    	/*** Tokens reserved for Founders and Team ***/
    
    	// 112,500,000 (11.25%) tokens will be eventually available for the team
    	// These tokens will be distributed every 3 month without a cliff within 4 years
    	// 7,031,250 tokens will be unlocked every 3 month
    
    	address public teamAllocation  = address(0x2222222222222222222222222222222222222222);
    	uint256 public teamTotal = 112500000e18;
    	uint256 public teamPeriodAmount = 7031250e18;
    	uint256 public teamUnvested = 0;
    	uint256 public teamCliff = 0;
    	uint256 public teamPeriodLength = 3 * 30 days;
    	uint8   public teamPeriodsNumber = 16;
    
    
    
    	/*** Tokens reserved for Community Building and Airdrop Campaigns ***/
    
    	// 60,000,000 (6%) tokens will be eventually available for the community
    	// 10,000,002 tokens will be available instantly without vesting
    	// 49,999,998 tokens will be distributed every 3 month without a cliff within 18 months
    	// 8,333,333 tokens will be unlocked every 3 month
    
    
    	address public communityAllocation  = address(0x3333333333333333333333333333333333333333);
    	uint256 public communityTotal = 60000000e18;
    	uint256 public communityPeriodAmount = 8333333e18;
    	uint256 public communityUnvested = 10000002e18;
    	uint256 public communityCliff = 0;
    	uint256 public communityPeriodLength = 3 * 30 days;
    	uint8   public communityPeriodsNumber = 6;
    
    
    
    	/*** Tokens reserved for Advisors, Legal and PR ***/
    
    	// 52,500,000 (5.25%) tokens will be eventually available for advisers
    	// 25,000,008 tokens will be available instantly without vesting
    	// 27 499 992 tokens will be distributed monthly without a cliff within 12 months
    	// 2,291,666 tokens will be unlocked every month
    
    	address public advisersAllocation  = address(0x4444444444444444444444444444444444444444);
    	uint256 public advisersTotal = 52500000e18;
    	uint256 public advisersPeriodAmount = 2291666e18;
    	uint256 public advisersUnvested = 25000008e18;
    	uint256 public advisersCliff = 0;
    	uint256 public advisersPeriodLength = 30 days;
    	uint8   public advisersPeriodsNumber = 12;
    
    
    	/// CONSTRUCTOR
    
    	function NexoToken() public {
    		//  Overall, 1,000,000,000 tokens exist
    		totalSupply = 1000000000e18;
    
    		balances[investorsAllocation] = investorsTotal;
    		balances[overdraftAllocation] = overdraftTotal;
    		balances[teamAllocation] = teamTotal;
    		balances[communityAllocation] = communityTotal;
    		balances[advisersAllocation] = advisersTotal;
    
    		// Unlock some tokens without vesting
    		allowed[investorsAllocation][msg.sender] = investorsTotal;
    		allowed[overdraftAllocation][msg.sender] = overdraftUnvested;
    		allowed[communityAllocation][msg.sender] = communityUnvested;
    		allowed[advisersAllocation][msg.sender] = advisersUnvested;
    	}
    
    	/// DISTRIBUTION
    
    	function distributeInvestorsTokens(address _to, uint256 _amountWithDecimals)
    		public
    		onlyOwner
    	{
    		require(transferFrom(investorsAllocation, _to, _amountWithDecimals));
    	}
    
    	/// VESTING
    
    	function withdrawOverdraftTokens(address _to, uint256 _amountWithDecimals)
    		public
    		onlyOwner
    	{
    		allowed[overdraftAllocation][msg.sender] = allowance(overdraftAllocation, msg.sender);
    		require(transferFrom(overdraftAllocation, _to, _amountWithDecimals));
    	}
    
    	function withdrawTeamTokens(address _to, uint256 _amountWithDecimals)
    		public
    		onlyOwner 
    	{
    		allowed[teamAllocation][msg.sender] = allowance(teamAllocation, msg.sender);
    		require(transferFrom(teamAllocation, _to, _amountWithDecimals));
    	}
    
    	function withdrawCommunityTokens(address _to, uint256 _amountWithDecimals)
    		public
    		onlyOwner 
    	{
    		allowed[communityAllocation][msg.sender] = allowance(communityAllocation, msg.sender);
    		require(transferFrom(communityAllocation, _to, _amountWithDecimals));
    	}
    
    	function withdrawAdvisersTokens(address _to, uint256 _amountWithDecimals)
    		public
    		onlyOwner 
    	{
    		allowed[advisersAllocation][msg.sender] = allowance(advisersAllocation, msg.sender);
    		require(transferFrom(advisersAllocation, _to, _amountWithDecimals));
    	}
    
    	/// @dev Overrides StandardToken.sol function
    	function allowance(address _owner, address _spender)
    		public
    		view
    		returns (uint256 remaining)
    	{   
    		if (_spender != owner) {
    			return allowed[_owner][_spender];
    		}
    
    		uint256 unlockedTokens;
    		uint256 spentTokens;
    
    		if (_owner == overdraftAllocation) {
    			unlockedTokens = _calculateUnlockedTokens(
    				overdraftCliff,
    				overdraftPeriodLength,
    				overdraftPeriodAmount,
    				overdraftPeriodsNumber,
    				overdraftUnvested
    			);
    			spentTokens = sub(overdraftTotal, balanceOf(overdraftAllocation));
    		} else if (_owner == teamAllocation) {
    			unlockedTokens = _calculateUnlockedTokens(
    				teamCliff,
    				teamPeriodLength,
    				teamPeriodAmount,
    				teamPeriodsNumber,
    				teamUnvested
    			);
    			spentTokens = sub(teamTotal, balanceOf(teamAllocation));
    		} else if (_owner == communityAllocation) {
    			unlockedTokens = _calculateUnlockedTokens(
    				communityCliff,
    				communityPeriodLength,
    				communityPeriodAmount,
    				communityPeriodsNumber,
    				communityUnvested
    			);
    			spentTokens = sub(communityTotal, balanceOf(communityAllocation));
    		} else if (_owner == advisersAllocation) {
    			unlockedTokens = _calculateUnlockedTokens(
    				advisersCliff,
    				advisersPeriodLength,
    				advisersPeriodAmount,
    				advisersPeriodsNumber,
    				advisersUnvested
    			);
    			spentTokens = sub(advisersTotal, balanceOf(advisersAllocation));
    		} else {
    			return allowed[_owner][_spender];
    		}
    
    		return sub(unlockedTokens, spentTokens);
    	}
    
    	/// @dev Overrides Owned.sol function
    	function confirmOwnership()
    		public
    		onlyPotentialOwner
    	{   
    		// Forbid the old owner to distribute investors' tokens
    		allowed[investorsAllocation][owner] = 0;
    
    		// Allow the new owner to distribute investors' tokens
    		allowed[investorsAllocation][msg.sender] = balanceOf(investorsAllocation);
    
    		// Forbid the old owner to withdraw any tokens from the reserves
    		allowed[overdraftAllocation][owner] = 0;
    		allowed[teamAllocation][owner] = 0;
    		allowed[communityAllocation][owner] = 0;
    		allowed[advisersAllocation][owner] = 0;
    
    		super.confirmOwnership();
    	}
    
    	function _calculateUnlockedTokens(
    		uint256 _cliff,
    		uint256 _periodLength,
    		uint256 _periodAmount,
    		uint8 _periodsNumber,
    		uint256 _unvestedAmount
    	)
    		private
    		view
    		returns (uint256) 
    	{
    		/* solium-disable-next-line security/no-block-members */
    		if (now < add(creationTime, _cliff)) {
    			return _unvestedAmount;
    		}
    		/* solium-disable-next-line security/no-block-members */
    		uint256 periods = div(sub(now, add(creationTime, _cliff)), _periodLength);
    		periods = periods > _periodsNumber ? _periodsNumber : periods;
    		return add(_unvestedAmount, mul(periods, _periodAmount));
    	}
    }