ETH Price: $3,774.82 (-0.16%)

Transaction Decoder

Block:
12003850 at Mar-09-2021 10:40:38 AM +UTC
Transaction Fee:
0.0127449 ETH $48.11
Gas Used:
127,449 Gas / 100 Gwei

Emitted Events:

177 CoinToken.Transfer( from=[Receiver] 0xd0eeb34f443782f375302bdb66e432c51ecdae9f, to=[Sender] 0xb5367dc03381e33c61457134c1ddeaff97bb15fe, tokens=20000000000000000000 )
178 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.0x7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5( 0x7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5, 0x000000000000000000000000b5367dc03381e33c61457134c1ddeaff97bb15fe, 000000000000000000000000000000000000000000000001158e460913d00000 )

Account State Difference:

  Address   Before After State Difference Code
(Spark Pool)
27.556874132999127732 Eth27.569619032999127732 Eth0.0127449
0xb5367dC0...F97BB15Fe
0.023047172 Eth
Nonce: 31
0.010302272 Eth
Nonce: 32
0.0127449
0xd0EeB34f...51eCDAe9f
0xE61fDAF4...163Cfa850

Execution Trace

0xd0eeb34f443782f375302bdb66e432c51ecdae9f.CALL( )
  • 0x6bfbacfdd75f2a4d2302d8ddb5a7cf9bb0289346.632447c9( )
    • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.STATICCALL( )
    • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.9f0825f7( )
    • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.e5e22999( )
    • CoinToken.transfer( _to=0xb5367dC03381e33c61457134C1ddeafF97BB15Fe, _amount=20000000000000000000 ) => ( success=True )
    • 0x6bfbacfdd75f2a4d2302d8ddb5a7cf9bb0289346.632447c9( )
      • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.STATICCALL( )
      • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.9f0825f7( )
      • 0xd0eeb34f443782f375302bdb66e432c51ecdae9f.e5e22999( )
        pragma solidity ^0.4.24;
        
        /**
         * @title SafeMath
         * @dev Math operations with safety checks that throw on error
         */
        library SafeMathLib{
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a * b;
            assert(a == 0 || c / a == b);
            return c;
          }
        
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
          }
        
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            assert(b <= a);
            return a - b;
          }
          
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        /**
         * @title Ownable
         * @dev The Ownable contract has an owner address, and provides basic authorization control
         * functions, this simplifies the implementation of "user permissions".
         */
        contract Ownable {
          address public owner;
          address public coinvest;
          mapping (address => bool) public admins;
        
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        
          /**
           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
           * account.
           */
          constructor() public {
            owner = msg.sender;
            coinvest = msg.sender;
            admins[owner] = true;
            admins[coinvest] = true;
          }
        
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
            require(msg.sender == owner);
            _;
          }
        
          modifier onlyCoinvest() {
              require(msg.sender == coinvest);
              _;
          }
        
          modifier onlyAdmin() {
              require(admins[msg.sender]);
              _;
          }
        
          /**
           * @dev Allows the current owner to transfer control of the contract to a newOwner.
           * @param newOwner The address to transfer ownership to.
           */
          function transferOwnership(address newOwner) onlyOwner public {
            require(newOwner != address(0));
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
          }
          
          /**
           * @dev Changes the Coinvest wallet that will receive funds from investment contract.
           * @param _newCoinvest The address of the new wallet.
          **/
          function transferCoinvest(address _newCoinvest) 
            external
            onlyCoinvest
          {
            require(_newCoinvest != address(0));
            coinvest = _newCoinvest;
          }
        
          /**
           * @dev Used to add admins who are allowed to add funds to the investment contract.
           * @param _user The address of the admin to add or remove.
           * @param _status True to add the user, False to remove the user.
          **/
          function alterAdmin(address _user, bool _status)
            external
            onlyCoinvest
          {
            require(_user != address(0));
            require(_user != coinvest);
            admins[_user] = _status;
          }
        
        }
        
        /**
         * @dev Abstract contract for approveAndCall.
        **/
        contract ApproveAndCallFallBack {
            function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
        }
        
        /**
         * @title Coin Utility Token
         * @dev ERC20 contract utilizing ERC865 structure (3esmit's implementation with alterations).
         * @dev to allow users to pay Ethereum fees in tokens.
         * @author Coin -- Robert M.C. Forster
        **/
        contract CoinToken is Ownable {
            using SafeMathLib for uint256;
            
            string public constant symbol = "COIN";
            string public constant name = "Coin Utility Token";
            
            uint8 public constant decimals = 18;
            uint256 private _totalSupply = 107142857 * (10 ** 18);
            
            // Function sigs to be used within contract for signature recovery.
            bytes4 internal constant transferSig = 0xa9059cbb;
            bytes4 internal constant approveSig = 0x095ea7b3;
            bytes4 internal constant increaseApprovalSig = 0xd73dd623;
            bytes4 internal constant decreaseApprovalSig = 0x66188463;
            bytes4 internal constant approveAndCallSig = 0xcae9ca51;
            bytes4 internal constant revokeHashSig = 0x70de43f1;
        
            // Balances for each account
            mapping(address => uint256) balances;
        
            // Owner of account approves the transfer of an amount to another account
            mapping(address => mapping (address => uint256)) allowed;
            
            // Mapping of past used hashes: true if already used.
            mapping(address => mapping (bytes32 => bool)) invalidHashes;
        
            event Transfer(address indexed from, address indexed to, uint tokens);
            event Approval(address indexed from, address indexed spender, uint tokens);
            event HashRedeemed(bytes32 indexed txHash, address indexed from);
        
            /**
             * @dev Set owner and beginning balance.
            **/
            constructor()
              public
            {
                balances[msg.sender] = _totalSupply;
            }
        
            /**
             * @dev approveAndCall reception used primarily to pay gas with other tokens.
            **/
            function receiveApproval(address _from, uint256 _amount, address _token, bytes _data) 
              public
            {
                require(msg.sender != address(this));
                require(address(this).delegatecall(_data));
                _from; _amount; _token;
            }
        
        /** ******************************** ERC20 ********************************* **/
        
            /**
             * @dev Transfers coins from one address to another.
             * @param _to The recipient of the transfer amount.
             * @param _amount The amount of tokens to transfer.
            **/
            function transfer(address _to, uint256 _amount) 
              public
            returns (bool success)
            {
                require(_transfer(msg.sender, _to, _amount));
                return true;
            }
            
            /**
             * @dev An allowed address can transfer tokens from another's address.
             * @param _from The owner of the tokens to be transferred.
             * @param _to The address to which the tokens will be transferred.
             * @param _amount The amount of tokens to be transferred.
            **/
            function transferFrom(address _from, address _to, uint _amount)
              public
            returns (bool success)
            {
                require(balances[_from] >= _amount && allowed[_from][msg.sender] >= _amount);
        
                allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_amount);
                require(_transfer(_from, _to, _amount));
                return true;
            }
            
            /**
             * @dev Approves a wallet to transfer tokens on one's behalf.
             * @param _spender The wallet approved to spend tokens.
             * @param _amount The amount of tokens approved to spend.
            **/
            function approve(address _spender, uint256 _amount) 
              public
            returns (bool success)
            {
                require(_approve(msg.sender, _spender, _amount));
                return true;
            }
            
            /**
             * @dev Increases the allowed amount for spender from msg.sender.
             * @param _spender The address to increase allowed amount for.
             * @param _amount The amount of tokens to increase allowed amount by.
            **/
            function increaseApproval(address _spender, uint256 _amount) 
              public
            returns (bool success)
            {
                require(_increaseApproval(msg.sender, _spender, _amount));
                return true;
            }
            
            /**
             * @dev Decreases the allowed amount for spender from msg.sender.
             * @param _spender The address to decrease allowed amount for.
             * @param _amount The amount of tokens to decrease allowed amount by.
            **/
            function decreaseApproval(address _spender, uint256 _amount) 
              public
            returns (bool success)
            {
                require(_decreaseApproval(msg.sender, _spender, _amount));
                return true;
            }
            
            /**
             * @dev Used to approve an address and call a function on it in the same transaction.
             * @dev _spender The address to be approved to spend COIN.
             * @dev _amount The amount of COIN to be approved to spend.
             * @dev _data The data to send to the called contract.
            **/
            function approveAndCall(address _spender, uint256 _amount, bytes _data) 
              public
            returns (bool success) 
            {
                require(_approve(msg.sender, _spender, _amount));
                ApproveAndCallFallBack(_spender).receiveApproval(msg.sender, _amount, address(this), _data);
                return true;
            }
        
        /** ****************************** Internal ******************************** **/
            
            /**
             * @dev Internal transfer for all functions that transfer.
             * @param _from The address that is transferring coins.
             * @param _to The receiving address of the coins.
             * @param _amount The amount of coins being transferred.
            **/
            function _transfer(address _from, address _to, uint256 _amount)
              internal
            returns (bool success)
            {
                require (_to != address(0), "Invalid transfer recipient address.");
                require(balances[_from] >= _amount, "Sender does not have enough balance.");
                
                balances[_from] = balances[_from].sub(_amount);
                balances[_to] = balances[_to].add(_amount);
                
                emit Transfer(_from, _to, _amount);
                return true;
            }
            
            /**
             * @dev Internal approve for all functions that require an approve.
             * @param _owner The owner who is allowing spender to use their balance.
             * @param _spender The wallet approved to spend tokens.
             * @param _amount The amount of tokens approved to spend.
            **/
            function _approve(address _owner, address _spender, uint256 _amount) 
              internal
            returns (bool success)
            {
                allowed[_owner][_spender] = _amount;
                emit Approval(_owner, _spender, _amount);
                return true;
            }
            
            /**
             * @dev Increases the allowed by "_amount" for "_spender" from "owner"
             * @param _owner The address that tokens may be transferred from.
             * @param _spender The address that may transfer these tokens.
             * @param _amount The amount of tokens to transfer.
            **/
            function _increaseApproval(address _owner, address _spender, uint256 _amount)
              internal
            returns (bool success)
            {
                allowed[_owner][_spender] = allowed[_owner][_spender].add(_amount);
                emit Approval(_owner, _spender, allowed[_owner][_spender]);
                return true;
            }
            
            /**
             * @dev Decreases the allowed by "_amount" for "_spender" from "_owner"
             * @param _owner The owner of the tokens to decrease allowed for.
             * @param _spender The spender whose allowed will decrease.
             * @param _amount The amount of tokens to decrease allowed by.
            **/
            function _decreaseApproval(address _owner, address _spender, uint256 _amount)
              internal
            returns (bool success)
            {
                if (allowed[_owner][_spender] <= _amount) allowed[_owner][_spender] = 0;
                else allowed[_owner][_spender] = allowed[_owner][_spender].sub(_amount);
                
                emit Approval(_owner, _spender, allowed[_owner][_spender]);
                return true;
            }
            
        /** ************************ Delegated Functions *************************** **/
        
            /**
             * @dev Called by delegate with a signed hash of the transaction data to allow a user
             * @dev to transfer tokens without paying gas in Ether (they pay in COIN instead).
             * @param _signature Signed hash of data for this transfer.
             * @param _to The address to transfer COIN to.
             * @param _value The amount of COIN to transfer.
             * @param _gasPrice Price (IN COIN) that will be paid per unit of gas by user to "delegate".
             * @param _nonce Nonce of the user's new transaction.
            **/
            function transferPreSigned(
                bytes _signature,
                address _to, 
                uint256 _value,
                uint256 _gasPrice, 
                uint256 _nonce) 
              public
            returns (bool) 
            {
                // Log starting gas left of transaction for later gas price calculations.
                uint256 gas = gasleft();
                
                // Recover signer address from signature; ensure address is valid.
                address from = recoverPreSigned(_signature, transferSig, _to, _value, "", _gasPrice, _nonce);
                require(from != address(0), "Invalid signature provided.");
                
                // Require the hash has not been used, declare it used.
                bytes32 txHash = getPreSignedHash(transferSig, _to, _value, "", _gasPrice, _nonce);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                // Internal transfer.
                require(_transfer(from, _to, _value));
        
                // If the delegate is charging, pay them for gas in COIN.
                if (_gasPrice > 0) {
                    // 35000 because of base fee of 21000 and ~14000 for the fee transfer.
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
                
                emit HashRedeemed(txHash, from);
                return true;
            }
            
            /**
             * @dev Called by a delegate with signed hash to approve a transaction for user.
             * @dev All variables equivalent to transfer except _to:
             * @param _to The address that will be approved to transfer COIN from user's wallet.
            **/
            function approvePreSigned(
                bytes _signature,
                address _to, 
                uint256 _value,
                uint256 _gasPrice, 
                uint256 _nonce) 
              public
            returns (bool) 
            {
                uint256 gas = gasleft();
                address from = recoverPreSigned(_signature, approveSig, _to, _value, "", _gasPrice, _nonce);
                require(from != address(0), "Invalid signature provided.");
        
                bytes32 txHash = getPreSignedHash(approveSig, _to, _value, "", _gasPrice, _nonce);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                require(_approve(from, _to, _value));
        
                if (_gasPrice > 0) {
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
        
                emit HashRedeemed(txHash, from);
                return true;
            }
            
            /**
             * @dev Used to increase the amount allowed for "_to" to spend from "from"
             * @dev A bare approve allows potentially nasty race conditions when using a delegate.
            **/
            function increaseApprovalPreSigned(
                bytes _signature,
                address _to, 
                uint256 _value,
                uint256 _gasPrice, 
                uint256 _nonce)
              public
            returns (bool) 
            {
                uint256 gas = gasleft();
                address from = recoverPreSigned(_signature, increaseApprovalSig, _to, _value, "", _gasPrice, _nonce);
                require(from != address(0), "Invalid signature provided.");
        
                bytes32 txHash = getPreSignedHash(increaseApprovalSig, _to, _value, "", _gasPrice, _nonce);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                require(_increaseApproval(from, _to, _value));
        
                if (_gasPrice > 0) {
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
                
                emit HashRedeemed(txHash, from);
                return true;
            }
            
            /**
             * @dev Added for the same reason as increaseApproval. Decreases to 0 if "_value" is greater than allowed.
            **/
            function decreaseApprovalPreSigned(
                bytes _signature,
                address _to, 
                uint256 _value, 
                uint256 _gasPrice, 
                uint256 _nonce) 
              public
            returns (bool) 
            {
                uint256 gas = gasleft();
                address from = recoverPreSigned(_signature, decreaseApprovalSig, _to, _value, "", _gasPrice, _nonce);
                require(from != address(0), "Invalid signature provided.");
        
                bytes32 txHash = getPreSignedHash(decreaseApprovalSig, _to, _value, "", _gasPrice, _nonce);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                require(_decreaseApproval(from, _to, _value));
        
                if (_gasPrice > 0) {
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
        
                emit HashRedeemed(txHash, from);
                return true;
            }
            
            /**
             * @dev approveAndCallPreSigned allows a user to approve a contract and call a function on it
             * @dev in the same transaction. As with the other presigneds, a delegate calls this with signed data from user.
             * @dev This function is the big reason we're using gas price and calculating gas use.
             * @dev Using this with the investment contract can result in varying gas costs.
             * @param _extraData The data to send to the contract.
            **/
            function approveAndCallPreSigned(
                bytes _signature,
                address _to, 
                uint256 _value,
                bytes _extraData,
                uint256 _gasPrice,
                uint256 _nonce) 
              public
            returns (bool) 
            {
                uint256 gas = gasleft();
                address from = recoverPreSigned(_signature, approveAndCallSig, _to, _value, _extraData, _gasPrice, _nonce);
                require(from != address(0), "Invalid signature provided.");
        
                bytes32 txHash = getPreSignedHash(approveAndCallSig, _to, _value, _extraData, _gasPrice, _nonce);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                if (_value > 0) require(_approve(from, _to, _value));
                ApproveAndCallFallBack(_to).receiveApproval(from, _value, address(this), _extraData);
        
                if (_gasPrice > 0) {
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
                
                emit HashRedeemed(txHash, from);
                return true;
            }
        
        /** *************************** Revoke PreSigned ************************** **/
            
            /**
             * @dev Revoke hash without going through a delegate.
             * @param _hashToRevoke The hash that you no longer want to be used.
            **/
            function revokeHash(bytes32 _hashToRevoke)
              public
            returns (bool)
            {
                invalidHashes[msg.sender][_hashToRevoke] = true;
                return true;
            }
            
            /**
             * @dev Revoke hash through a delegate.
             * @param _signature The signature allowing this revocation.
             * @param _hashToRevoke The hash that you would like revoked.
             * @param _gasPrice The amount of token wei to be paid for each uint of gas.
            **/
            function revokeHashPreSigned(
                bytes _signature,
                bytes32 _hashToRevoke,
                uint256 _gasPrice)
              public
            returns (bool)
            {
                uint256 gas = gasleft();
                address from = recoverRevokeHash(_signature, _hashToRevoke, _gasPrice);
                require(from != address(0), "Invalid signature provided.");
                
                bytes32 txHash = getRevokeHash(_hashToRevoke, _gasPrice);
                require(!invalidHashes[from][txHash], "Transaction has already been executed.");
                invalidHashes[from][txHash] = true;
        
                invalidHashes[from][_hashToRevoke] = true;
                
                if (_gasPrice > 0) {
                    gas = 35000 + gas.sub(gasleft());
                    require(_transfer(from, tx.origin, _gasPrice.mul(gas)), "Gas cost could not be paid.");
                }
                
                emit HashRedeemed(txHash, from);
                return true;
            }
            
            /**
             * @dev Get hash for a revocation.
             * @param _hashToRevoke The signature to be revoked.
             * @param _gasPrice The amount to be paid to delegate for sending this tx.
            **/
            function getRevokeHash(bytes32 _hashToRevoke, uint256 _gasPrice)
              public
              view
            returns (bytes32 txHash)
            {
                return keccak256(abi.encodePacked(address(this), revokeHashSig, _hashToRevoke, _gasPrice));
            }
        
            /**
             * @dev Recover the address from a revocation hash.
             * @param _hashToRevoke The hash to be revoked.
             * @param _signature The signature allowing this revocation.
             * @param _gasPrice The amount of token wei to be paid for each unit of gas.
            **/
            function recoverRevokeHash(bytes _signature, bytes32 _hashToRevoke, uint256 _gasPrice)
              public
              view
            returns (address from)
            {
                return ecrecoverFromSig(getSignHash(getRevokeHash(_hashToRevoke, _gasPrice)), _signature);
            }
            
        /** ************************** PreSigned Constants ************************ **/
        
            /**
             * @dev Used in frontend and contract to get hashed data of any given pre-signed transaction.
             * @param _to The address to transfer COIN to.
             * @param _value The amount of COIN to be transferred.
             * @param _extraData Extra data of tx if needed. Transfers and approves will leave this null.
             * @param _function Function signature of the pre-signed function being used.
             * @param _gasPrice The agreed-upon amount of COIN to be paid per unit of gas.
             * @param _nonce The user's nonce of the new transaction.
            **/
            function getPreSignedHash(
                bytes4 _function,
                address _to, 
                uint256 _value,
                bytes _extraData,
                uint256 _gasPrice,
                uint256 _nonce)
              public
              view
            returns (bytes32 txHash) 
            {
                return keccak256(abi.encodePacked(address(this), _function, _to, _value, _extraData, _gasPrice, _nonce));
            }
            
            /**
             * @dev Recover an address from a signed pre-signed hash.
             * @param _sig The signed hash.
             * @param _function The function signature for function being called.
             * @param _to The address to transfer/approve/transferFrom/etc. tokens to.
             * @param _value The amont of tokens to transfer/approve/etc.
             * @param _extraData The extra data included in the transaction, if any.
             * @param _gasPrice The amount of token wei to be paid to the delegate for each unit of gas.
             * @param _nonce The user's nonce for this transaction.
            **/
            function recoverPreSigned(
                bytes _sig,
                bytes4 _function,
                address _to,
                uint256 _value,
                bytes _extraData,
                uint256 _gasPrice,
                uint256 _nonce) 
              public
              view
            returns (address recovered)
            {
                return ecrecoverFromSig(getSignHash(getPreSignedHash(_function, _to, _value, _extraData, _gasPrice, _nonce)), _sig);
            }
            
            /**
             * @dev Add signature prefix to hash for recovery à la ERC191.
             * @param _hash The hashed transaction to add signature prefix to.
            **/
            function getSignHash(bytes32 _hash)
              public
              pure
            returns (bytes32 signHash)
            {
                return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash));
            }
        
            /**
             * @dev Helps to reduce stack depth problems for delegations. Thank you to Bokky for this!
             * @param hash The hash of signed data for the transaction.
             * @param sig Contains r, s, and v for recovery of address from the hash.
            **/
            function ecrecoverFromSig(bytes32 hash, bytes sig) 
              public 
              pure 
            returns (address recoveredAddress) 
            {
                bytes32 r;
                bytes32 s;
                uint8 v;
                if (sig.length != 65) return address(0);
                assembly {
                    r := mload(add(sig, 32))
                    s := mload(add(sig, 64))
                    // Here we are loading the last 32 bytes. We exploit the fact that 'mload' will pad with zeroes if we overread.
                    // There is no 'mload8' to do this, but that would be nicer.
                    v := byte(0, mload(add(sig, 96)))
                }
                // Albeit non-transactional signatures are not specified by the YP, one would expect it to match the YP range of [27, 28]
                // geth uses [0, 1] and some clients have followed. This might change, see https://github.com/ethereum/go-ethereum/issues/2053
                if (v < 27) v += 27;
                if (v != 27 && v != 28) return address(0);
                return ecrecover(hash, v, r, s);
            }
        
        /** ****************************** Constants ******************************* **/
            
            /**
             * @dev Return total supply of token.
            **/
            function totalSupply() 
              external
              view 
             returns (uint256)
            {
                return _totalSupply;
            }
        
            /**
             * @dev Return balance of a certain address.
             * @param _owner The address whose balance we want to check.
            **/
            function balanceOf(address _owner)
              external
              view 
            returns (uint256) 
            {
                return balances[_owner];
            }
            
            /**
             * @dev Allowed amount for a user to spend of another's tokens.
             * @param _owner The owner of the tokens approved to spend.
             * @param _spender The address of the user allowed to spend the tokens.
            **/
            function allowance(address _owner, address _spender) 
              external
              view 
            returns (uint256) 
            {
                return allowed[_owner][_spender];
            }
            
        /** ****************************** onlyOwner ******************************* **/
            
            /**
             * @dev Allow the owner to take ERC20 tokens off of this contract if they are accidentally sent.
            **/
            function tokenEscape(address _tokenContract)
              external
              onlyOwner
            {
                CoinToken lostToken = CoinToken(_tokenContract);
                
                uint256 stuckTokens = lostToken.balanceOf(address(this));
                lostToken.transfer(owner, stuckTokens);
            }
            
        }