ETH Price: $2,246.67 (+6.09%)

Transaction Decoder

Block:
7619126 at Apr-22-2019 06:48:46 PM +UTC
Transaction Fee:
0.00004160835 ETH $0.09
Gas Used:
26,418 Gas / 1.575 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
0x419B8ED1...c0A4Efb97
0xBA2DcA5D...F51bC2762
0.091812031708409864 Eth
Nonce: 12
0.091770423358409864 Eth
Nonce: 13
0.00004160835
(Ethermine)
286.327895800133693699 Eth286.327937408483693699 Eth0.00004160835

Execution Trace

AltToken.transfer( _to=0xE0Cd6754B98c34208eEa54839CFc9cd00d7b4AA7, _value=1453700000000000000000 ) => ( success=True )
  • UserRegistry.knownAddress( _who=0xBA2DcA5DDB8aaAE17bCCe56ffE701C4F51bC2762 ) => ( False )
    File 1 of 2: AltToken
    pragma solidity ^0.4.18;
    
    contract TokenRecipient {
      function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; 
    }
    
    /**
     * @title ERC20Basic
     * @dev Simpler version of ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/179
     */
    contract ERC20Basic {
      uint256 public totalSupply;
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns (bool);
      event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that throw on error
     */
    library SafeMath {
      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;
      }
    
      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 Basic token
     * @dev Basic version of StandardToken, with no allowances.
     */
    contract BasicToken is ERC20Basic {
      using SafeMath for uint256;
    
      mapping(address => uint256) balances;
    
      /**
      * @dev transfer token for a specified address
      * @param _to The address to transfer to.
      * @param _value The amount to be transferred.
      */
      function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[msg.sender]);
    
        // SafeMath.sub will throw if there is not enough balance.
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        Transfer(msg.sender, _to, _value);
        return true;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param _owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
      }
    
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    contract ERC20 is ERC20Basic {
      function allowance(address owner, address spender) public view returns (uint256);
      function transferFrom(address from, address to, uint256 value) public returns (bool);
      function approve(address spender, uint256 value) public returns (bool);
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard token.
     * @dev https://github.com/ethereum/EIPs/issues/20
     * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
     */
    contract StandardToken is ERC20, BasicToken {
    
      mapping (address => mapping (address => uint256)) internal allowed;
    
    
      /**
       * @dev Transfer tokens from one address to another
       * @param _from address The address which you want to send tokens from
       * @param _to address The address which you want to transfer to
       * @param _value uint256 the amount of tokens to be transferred
       */
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
    
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        Transfer(_from, _to, _value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       *
       * Beware that changing an allowance with this method brings the risk that someone may use both the old
       * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
       * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       * @param _spender The address which will spend the funds.
       * @param _value The amount of tokens to be spent.
       */
      function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
      }
    
      /**
       * @dev Function to check the amount of tokens that an owner allowed to a spender.
       * @param _owner address The address which owns the funds.
       * @param _spender address The address which will spend the funds.
       * @return A uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(address _owner, address _spender) public view returns (uint256) {
        return allowed[_owner][_spender];
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _addedValue The amount of tokens to increase the allowance by.
       */
      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       *
       * approve should be called when allowed[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param _spender The address which will spend the funds.
       * @param _subtractedValue The amount of tokens to decrease the allowance by.
       */
      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
        } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
      }
    
    }
    
    contract ApproveAndCallToken is StandardToken {
      function approveAndCall(address _spender, uint _value, bytes _data) public returns (bool) {
        TokenRecipient spender = TokenRecipient(_spender);
        if (approve(_spender, _value)) {
          spender.receiveApproval(msg.sender, _value, this, _data);
          return true;
        }
        return false;
      }
    
      // ERC223 Token improvement to send tokens to smart-contracts
      function transfer(address _to, uint _value) public returns (bool success) { 
        //standard function transfer similar to ERC20 transfer with no _data
        //added due to backwards compatibility reasons
        bytes memory empty;
        if (isContract(_to)) {
            return transferToContract(_to, _value, empty);
        }
        else {
            return super.transfer(_to, _value);
        }
      }
    
      //assemble the given address bytecode. If bytecode exists then the _addr is a contract.
      function isContract(address _addr) private view returns (bool) {
        uint length;
        assembly {
          //retrieve the size of the code on target address, this needs assembly
          length := extcodesize(_addr)
        }
        return (length>0);
      }
    
      //function that is called when transaction target is a contract
      function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
        return approveAndCall(_to, _value, _data);
      }
    }
    
    contract UserRegistryInterface {
      event AddAddress(address indexed who);
      event AddIdentity(address indexed who);
    
      function knownAddress(address _who) public constant returns(bool);
      function hasIdentity(address _who) public constant returns(bool);
      function systemAddresses(address _to, address _from) public constant returns(bool);
    }
    
    /**
     * @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;
    
    
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function Ownable() public {
        owner = msg.sender;
      }
    
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
    
      /**
       * @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) public onlyOwner {
        require(newOwner != address(0));
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
      }
    
    }
    
    contract TokenPolicy is StandardToken, Ownable {
      bool public unfrozen;
      UserRegistryInterface public userRegistry;
    
      function TokenPolicy(address registry) public {
        require(registry != 0x0);
        userRegistry = UserRegistryInterface(registry);
      }
    
      event Unfrezee();
    
      modifier shouldPassPolicy(address _from, address _to) {
        // KYC policy
        require(
          !userRegistry.knownAddress(_from) || 
           userRegistry.hasIdentity(_from) || 
           userRegistry.systemAddresses(_to, _from));
    
        // Freeze policy
        require(unfrozen || userRegistry.systemAddresses(_to, _from));
    
        _;
      }
      function transfer(address _to, uint256 _value) shouldPassPolicy(msg.sender, _to) public returns (bool) {
        return super.transfer(_to, _value);
      }
    
      function transferFrom(address _from, address _to, uint256 _value) shouldPassPolicy(_from, _to) public returns (bool) {
        return super.transferFrom(_from, _to, _value);
      }
    
      function unfrezee() onlyOwner public returns (bool) {
        require(!unfrozen);
        unfrozen = true;
      }
    }
    
    /**
     * @title Mintable token
     * @dev Simple ERC20 Token example, with mintable token creation
     * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
     * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
     */
    
    contract MintableToken is StandardToken, Ownable {
      event Mint(address indexed to, uint256 amount);
      event MintFinished();
    
      bool public mintingFinished = false;
    
    
      modifier canMint() {
        require(!mintingFinished);
        _;
      }
    
      /**
       * @dev Function to mint tokens
       * @param _to The address that will receive the minted tokens.
       * @param _amount The amount of tokens to mint.
       * @return A boolean that indicates if the operation was successful.
       */
      function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
        totalSupply = totalSupply.add(_amount);
        balances[_to] = balances[_to].add(_amount);
        Mint(_to, _amount);
        Transfer(address(0), _to, _amount);
        return true;
      }
    
      /**
       * @dev Function to stop minting new tokens.
       * @return True if the operation was successful.
       */
      function finishMinting() onlyOwner canMint public returns (bool) {
        mintingFinished = true;
        MintFinished();
        return true;
      }
    }
    
    contract DefaultToken is MintableToken, TokenPolicy, ApproveAndCallToken {
      using SafeMath for uint;
    
      string public name;
      string public ticker;
      uint public decimals;
      
      function DefaultToken(string _name, string _ticker, uint _decimals, address _registry) 
        ApproveAndCallToken()
        MintableToken()
        TokenPolicy(_registry) public {
        name = _name;
        ticker = _ticker;
        decimals = _decimals;
      }
    
      function takeAway(address _holder, address _to) onlyOwner public returns (bool) {
        require(userRegistry.knownAddress(_holder) && !userRegistry.hasIdentity(_holder));
    
        uint allBalance = balances[_holder];
        balances[_to] = balances[_to].add(allBalance);
        balances[_holder] = 0;
        
        Transfer(_holder, _to, allBalance);
      }
    }
    
    contract AltToken is DefaultToken {
      function AltToken(address _registry) DefaultToken("AltEstate token", "ALT", 18, _registry) public {
      }
    }

    File 2 of 2: UserRegistry
    pragma solidity ^0.4.18;
    
    contract UserRegistryInterface {
      event AddAddress(address indexed who);
      event AddIdentity(address indexed who);
    
      function knownAddress(address _who) public constant returns(bool);
      function hasIdentity(address _who) public constant returns(bool);
      function systemAddresses(address _to, address _from) public constant returns(bool);
    }
    
    contract MultiOwners {
    
        event AccessGrant(address indexed owner);
        event AccessRevoke(address indexed owner);
        
        mapping(address => bool) owners;
        address public publisher;
    
        function MultiOwners() public {
            owners[msg.sender] = true;
            publisher = msg.sender;
        }
    
        modifier onlyOwner() { 
            require(owners[msg.sender] == true);
            _; 
        }
    
        function isOwner() public constant returns (bool) {
            return owners[msg.sender] ? true : false;
        }
    
        function checkOwner(address maybe_owner) public constant returns (bool) {
            return owners[maybe_owner] ? true : false;
        }
    
        function grant(address _owner) onlyOwner public {
            owners[_owner] = true;
            AccessGrant(_owner);
        }
    
        function revoke(address _owner) onlyOwner public {
            require(_owner != publisher);
            require(msg.sender != _owner);
    
            owners[_owner] = false;
            AccessRevoke(_owner);
        }
    }
    
    contract UserRegistry is MultiOwners, UserRegistryInterface {
      mapping (address => bool) internal addresses;
      mapping (address => bool) internal identities;
      mapping (address => bool) internal system;
    
      function addAddress(address _who) onlyOwner public returns(bool) {
        require(!knownAddress(_who));
        addresses[_who] = true;
        AddAddress(_who);
        return true;
      }
    
      function addSystem(address _address) onlyOwner public returns(bool) {
        system[_address] = true;
        return true;
      }
    
      function addIdentity(address _who) onlyOwner public returns(bool) {
        require(!hasIdentity(_who));
        if(!addresses[_who]) {
          addresses[_who] = true;
          AddAddress(_who);
        }
        identities[_who] = true;
        AddIdentity(_who);
        return true;
      }
      
      function knownAddress(address _who) public constant returns(bool) {
        return addresses[_who];
      }
    
      function hasIdentity(address _who) public constant returns(bool) {
        return knownAddress(_who) && identities[_who];
      }
    
      function systemAddress(address _where) public constant returns(bool) {
        return system[_where];
      }
    
      function systemAddresses(address _to, address _from) public constant returns(bool) {
        return systemAddress(_to) || systemAddress(_from);
      }
    }