ETH Price: $3,803.76 (-1.91%)
Gas: 8 Gwei

Transaction Decoder

Block:
18996763 at Jan-13-2024 08:25:11 AM +UTC
Transaction Fee:
0.00129470317474124 ETH $4.92
Gas Used:
79,640 Gas / 16.256945941 Gwei

Emitted Events:

312 RING.Transfer( src=[Receiver] OwnedUpgradeabilityProxy, dst=[Sender] 0x122a1e9a4f2f6055f0f3fe60eb98ba438e560108, wad=25000000000000000000000 )
313 OwnedUpgradeabilityProxy.0x6fcd44939c95364863265e2908a0edea0cc534e2a03003586f8202855cc6b145( 0x6fcd44939c95364863265e2908a0edea0cc534e2a03003586f8202855cc6b145, 0x0000000000000000000000000000000000000000000000000000000000000307, 0x000000000000000000000000122a1e9a4f2f6055f0f3fe60eb98ba438e560108, 00000000000000000000000000000000000000000000054b40b1f852bda00000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x122A1E9a...38e560108
0.087256107224808642 Eth
Nonce: 595
0.085961404050067402 Eth
Nonce: 596
0.00129470317474124
(Titan Builder)
27.468361066045601575 Eth27.468429741566790575 Eth0.000068675521189
0x649fDF6e...0fbD82D88
0x9469D013...e535ec483

Execution Trace

OwnedUpgradeabilityProxy.5f8534ae( )
  • GringottsBank.claimDeposit( _depositID=775 )
    • SettingsRegistry.addressOf( _propertyName=434F4E54524143545F52494E475F45524332305F544F4B454E00000000000000 ) => ( 0x9469D013805bFfB7D3DEBe5E7839237e535ec483 )
    • RING.transfer( dst=0x122A1E9a4F2F6055f0F3FE60eB98ba438e560108, wad=25000000000000000000000 ) => ( True )
      File 1 of 4: OwnedUpgradeabilityProxy
      // Dependency file: contracts/Proxy.sol
      
      // pragma solidity ^0.4.21;
      
      /**
       * @title Proxy
       * @dev Gives the possibility to delegate any call to a foreign implementation.
       */
      contract Proxy {
        /**
        * @dev Tells the address of the implementation where every call will be delegated.
        * @return address of the implementation to which it will be delegated
        */
        function implementation() public view returns (address);
      
        /**
        * @dev Fallback function allowing to perform a delegatecall to the given implementation.
        * This function will return whatever the implementation call returns
        */
        function () payable public {
          address _impl = implementation();
          require(_impl != address(0));
      
          assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize)
            let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
            let size := returndatasize
            returndatacopy(ptr, 0, size)
      
            switch result
            case 0 { revert(ptr, size) }
            default { return(ptr, size) }
          }
        }
      }
      
      
      // Dependency file: contracts/UpgradeabilityProxy.sol
      
      // pragma solidity ^0.4.21;
      
      // import 'contracts/Proxy.sol';
      
      /**
       * @title UpgradeabilityProxy
       * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded
       */
      contract UpgradeabilityProxy is Proxy {
        /**
         * @dev This event will be emitted every time the implementation gets upgraded
         * @param implementation representing the address of the upgraded implementation
         */
        event Upgraded(address indexed implementation);
      
        // Storage position of the address of the current implementation
        bytes32 private constant implementationPosition = keccak256("org.zeppelinos.proxy.implementation");
      
        /**
         * @dev Constructor function
         */
        function UpgradeabilityProxy() public {}
      
        /**
         * @dev Tells the address of the current implementation
         * @return address of the current implementation
         */
        function implementation() public view returns (address impl) {
          bytes32 position = implementationPosition;
          assembly {
            impl := sload(position)
          }
        }
      
        /**
         * @dev Sets the address of the current implementation
         * @param newImplementation address representing the new implementation to be set
         */
        function setImplementation(address newImplementation) internal {
          bytes32 position = implementationPosition;
          assembly {
            sstore(position, newImplementation)
          }
        }
      
        /**
         * @dev Upgrades the implementation address
         * @param newImplementation representing the address of the new implementation to be set
         */
        function _upgradeTo(address newImplementation) internal {
          address currentImplementation = implementation();
          require(currentImplementation != newImplementation);
          setImplementation(newImplementation);
          emit Upgraded(newImplementation);
        }
      }
      
      
      // Root file: contracts/OwnedUpgradeabilityProxy.sol
      
      pragma solidity ^0.4.21;
      
      // import 'contracts/UpgradeabilityProxy.sol';
      
      /**
       * @title OwnedUpgradeabilityProxy
       * @dev This contract combines an upgradeability proxy with basic authorization control functionalities
       */
      contract OwnedUpgradeabilityProxy is UpgradeabilityProxy {
        /**
        * @dev Event to show ownership has been transferred
        * @param previousOwner representing the address of the previous owner
        * @param newOwner representing the address of the new owner
        */
        event ProxyOwnershipTransferred(address previousOwner, address newOwner);
      
        // Storage position of the owner of the contract
        bytes32 private constant proxyOwnerPosition = keccak256("org.zeppelinos.proxy.owner");
      
        /**
        * @dev the constructor sets the original owner of the contract to the sender account.
        */
        function OwnedUpgradeabilityProxy() public {
          setUpgradeabilityOwner(msg.sender);
        }
      
        /**
        * @dev Throws if called by any account other than the owner.
        */
        modifier onlyProxyOwner() {
          require(msg.sender == proxyOwner());
          _;
        }
      
        /**
         * @dev Tells the address of the owner
         * @return the address of the owner
         */
        function proxyOwner() public view returns (address owner) {
          bytes32 position = proxyOwnerPosition;
          assembly {
            owner := sload(position)
          }
        }
      
        /**
         * @dev Sets the address of the owner
         */
        function setUpgradeabilityOwner(address newProxyOwner) internal {
          bytes32 position = proxyOwnerPosition;
          assembly {
            sstore(position, newProxyOwner)
          }
        }
      
        /**
         * @dev Allows the current owner to transfer control of the contract to a newOwner.
         * @param newOwner The address to transfer ownership to.
         */
        function transferProxyOwnership(address newOwner) public onlyProxyOwner {
          require(newOwner != address(0));
          emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
          setUpgradeabilityOwner(newOwner);
        }
      
        /**
         * @dev Allows the proxy owner to upgrade the current version of the proxy.
         * @param implementation representing the address of the new implementation to be set.
         */
        function upgradeTo(address implementation) public onlyProxyOwner {
          _upgradeTo(implementation);
        }
      
        /**
         * @dev Allows the proxy owner to upgrade the current version of the proxy and call the new implementation
         * to initialize whatever is needed through a low level call.
         * @param implementation representing the address of the new implementation to be set.
         * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
         * signature of the implementation to be called with the needed payload
         */
        function upgradeToAndCall(address implementation, bytes data) payable public onlyProxyOwner {
          upgradeTo(implementation);
          require(this.call.value(msg.value)(data));
        }
      }

      File 2 of 4: RING
      pragma solidity ^0.4.23;
      
      contract DSAuthority {
          function canCall(
              address src, address dst, bytes4 sig
          ) public view returns (bool);
      }
      
      contract DSAuthEvents {
          event LogSetAuthority (address indexed authority);
          event LogSetOwner     (address indexed owner);
      }
      
      contract DSAuth is DSAuthEvents {
          DSAuthority  public  authority;
          address      public  owner;
      
          constructor() public {
              owner = msg.sender;
              emit LogSetOwner(msg.sender);
          }
      
          function setOwner(address owner_)
              public
              auth
          {
              owner = owner_;
              emit LogSetOwner(owner);
          }
      
          function setAuthority(DSAuthority authority_)
              public
              auth
          {
              authority = authority_;
              emit LogSetAuthority(authority);
          }
      
          modifier auth {
              require(isAuthorized(msg.sender, msg.sig));
              _;
          }
      
          function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
              if (src == address(this)) {
                  return true;
              } else if (src == owner) {
                  return true;
              } else if (authority == DSAuthority(0)) {
                  return false;
              } else {
                  return authority.canCall(src, this, sig);
              }
          }
      }
      
      contract DSNote {
          event LogNote(
              bytes4   indexed  sig,
              address  indexed  guy,
              bytes32  indexed  foo,
              bytes32  indexed  bar,
              uint              wad,
              bytes             fax
          ) anonymous;
      
          modifier note {
              bytes32 foo;
              bytes32 bar;
      
              assembly {
                  foo := calldataload(4)
                  bar := calldataload(36)
              }
      
              emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
      
              _;
          }
      }
      
      contract DSStop is DSNote, DSAuth {
      
          bool public stopped;
      
          modifier stoppable {
              require(!stopped);
              _;
          }
          function stop() public auth note {
              stopped = true;
          }
          function start() public auth note {
              stopped = false;
          }
      
      }
      
      contract ERC20Events {
          event Approval(address indexed src, address indexed guy, uint wad);
          event Transfer(address indexed src, address indexed dst, uint wad);
      }
      
      contract ERC20 is ERC20Events {
          function totalSupply() public view returns (uint);
          function balanceOf(address guy) public view returns (uint);
          function allowance(address src, address guy) public view returns (uint);
      
          function approve(address guy, uint wad) public returns (bool);
          function transfer(address dst, uint wad) public returns (bool);
          function transferFrom(
              address src, address dst, uint wad
          ) public returns (bool);
      }
      
      contract DSMath {
          function add(uint x, uint y) internal pure returns (uint z) {
              require((z = x + y) >= x);
          }
          function sub(uint x, uint y) internal pure returns (uint z) {
              require((z = x - y) <= x);
          }
          function mul(uint x, uint y) internal pure returns (uint z) {
              require(y == 0 || (z = x * y) / y == x);
          }
      
          function min(uint x, uint y) internal pure returns (uint z) {
              return x <= y ? x : y;
          }
          function max(uint x, uint y) internal pure returns (uint z) {
              return x >= y ? x : y;
          }
          function imin(int x, int y) internal pure returns (int z) {
              return x <= y ? x : y;
          }
          function imax(int x, int y) internal pure returns (int z) {
              return x >= y ? x : y;
          }
      
          uint constant WAD = 10 ** 18;
          uint constant RAY = 10 ** 27;
      
          function wmul(uint x, uint y) internal pure returns (uint z) {
              z = add(mul(x, y), WAD / 2) / WAD;
          }
          function rmul(uint x, uint y) internal pure returns (uint z) {
              z = add(mul(x, y), RAY / 2) / RAY;
          }
          function wdiv(uint x, uint y) internal pure returns (uint z) {
              z = add(mul(x, WAD), y / 2) / y;
          }
          function rdiv(uint x, uint y) internal pure returns (uint z) {
              z = add(mul(x, RAY), y / 2) / y;
          }
      
          // This famous algorithm is called "exponentiation by squaring"
          // and calculates x^n with x as fixed-point and n as regular unsigned.
          //
          // It's O(log n), instead of O(n) for naive repeated multiplication.
          //
          // These facts are why it works:
          //
          //  If n is even, then x^n = (x^2)^(n/2).
          //  If n is odd,  then x^n = x * x^(n-1),
          //   and applying the equation for even x gives
          //    x^n = x * (x^2)^((n-1) / 2).
          //
          //  Also, EVM division is flooring and
          //    floor[(n-1) / 2] = floor[n / 2].
          //
          function rpow(uint x, uint n) internal pure returns (uint z) {
              z = n % 2 != 0 ? x : RAY;
      
              for (n /= 2; n != 0; n /= 2) {
                  x = rmul(x, x);
      
                  if (n % 2 != 0) {
                      z = rmul(z, x);
                  }
              }
          }
      }
      
      
      contract DSTokenBase is ERC20, DSMath {
          uint256                                            _supply;
          mapping (address => uint256)                       _balances;
          mapping (address => mapping (address => uint256))  _approvals;
      
          constructor(uint supply) public {
              _balances[msg.sender] = supply;
              _supply = supply;
          }
      
          function totalSupply() public view returns (uint) {
              return _supply;
          }
          function balanceOf(address src) public view returns (uint) {
              return _balances[src];
          }
          function allowance(address src, address guy) public view returns (uint) {
              return _approvals[src][guy];
          }
      
          function transfer(address dst, uint wad) public returns (bool) {
              return transferFrom(msg.sender, dst, wad);
          }
      
          function transferFrom(address src, address dst, uint wad)
              public
              returns (bool)
          {
              if (src != msg.sender) {
                  _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
              }
      
              _balances[src] = sub(_balances[src], wad);
              _balances[dst] = add(_balances[dst], wad);
      
              emit Transfer(src, dst, wad);
      
              return true;
          }
      
          function approve(address guy, uint wad) public returns (bool) {
              _approvals[msg.sender][guy] = wad;
      
              emit Approval(msg.sender, guy, wad);
      
              return true;
          }
      }
      
      contract DSToken is DSTokenBase(0), DSStop {
      
          bytes32  public  symbol;
          uint256  public  decimals = 18; // standard token precision. override to customize
      
          constructor(bytes32 symbol_) public {
              symbol = symbol_;
          }
      
          event Mint(address indexed guy, uint wad);
          event Burn(address indexed guy, uint wad);
      
          function approve(address guy) public stoppable returns (bool) {
              return super.approve(guy, uint(-1));
          }
      
          function approve(address guy, uint wad) public stoppable returns (bool) {
              return super.approve(guy, wad);
          }
      
          function transferFrom(address src, address dst, uint wad)
              public
              stoppable
              returns (bool)
          {
              if (src != msg.sender && _approvals[src][msg.sender] != uint(-1)) {
                  _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
              }
      
              _balances[src] = sub(_balances[src], wad);
              _balances[dst] = add(_balances[dst], wad);
      
              emit Transfer(src, dst, wad);
      
              return true;
          }
      
          function push(address dst, uint wad) public {
              transferFrom(msg.sender, dst, wad);
          }
          function pull(address src, uint wad) public {
              transferFrom(src, msg.sender, wad);
          }
          function move(address src, address dst, uint wad) public {
              transferFrom(src, dst, wad);
          }
      
          function mint(uint wad) public {
              mint(msg.sender, wad);
          }
          function burn(uint wad) public {
              burn(msg.sender, wad);
          }
          function mint(address guy, uint wad) public auth stoppable {
              _balances[guy] = add(_balances[guy], wad);
              _supply = add(_supply, wad);
              emit Mint(guy, wad);
          }
          function burn(address guy, uint wad) public auth stoppable {
              if (guy != msg.sender && _approvals[guy][msg.sender] != uint(-1)) {
                  _approvals[guy][msg.sender] = sub(_approvals[guy][msg.sender], wad);
              }
      
              _balances[guy] = sub(_balances[guy], wad);
              _supply = sub(_supply, wad);
              emit Burn(guy, wad);
          }
      
          // Optional token name
          bytes32   public  name = "";
      
          function setName(bytes32 name_) public auth {
              name = name_;
          }
      }
      
      /// @title ERC223ReceivingContract - Standard contract implementation for compatibility with ERC223 tokens.
      interface ERC223ReceivingContract {
      
          /// @dev Function that is called when a user or another contract wants to transfer funds.
          /// @param _from Transaction initiator, analogue of msg.sender
          /// @param _value Number of tokens to transfer.
          /// @param _data Data containig a function signature and/or parameters
          function tokenFallback(address _from, uint256 _value, bytes _data) public;
      }
      
      /// @dev The token controller contract must implement these functions
      contract TokenController {
          /// @notice Called when `_owner` sends ether to the MiniMe Token contract
          /// @param _owner The address that sent the ether to create tokens
          /// @return True if the ether is accepted, false if it throws
          function proxyPayment(address _owner, bytes4 sig, bytes data) payable public returns (bool);
      
          /// @notice Notifies the controller about a token transfer allowing the
          ///  controller to react if desired
          /// @param _from The origin of the transfer
          /// @param _to The destination of the transfer
          /// @param _amount The amount of the transfer
          /// @return False if the controller does not authorize the transfer
          function onTransfer(address _from, address _to, uint _amount) public returns (bool);
      
          /// @notice Notifies the controller about an approval allowing the
          ///  controller to react if desired
          /// @param _owner The address that calls `approve()`
          /// @param _spender The spender in the `approve()` call
          /// @param _amount The amount in the `approve()` call
          /// @return False if the controller does not authorize the approval
          function onApprove(address _owner, address _spender, uint _amount) public returns (bool);
      }
      
      interface ApproveAndCallFallBack {
          function receiveApproval(address from, uint256 _amount, address _token, bytes _data) public;
      }
      
      interface ERC223 {
          function transfer(address to, uint amount, bytes data) public returns (bool ok);
      
          function transferFrom(address from, address to, uint256 amount, bytes data) public returns (bool ok);
      
          event ERC223Transfer(address indexed from, address indexed to, uint amount, bytes data);
      }
      
      contract ISmartToken {
          function transferOwnership(address _newOwner) public;
          function acceptOwnership() public;
      
          function disableTransfers(bool _disable) public;
          function issue(address _to, uint256 _amount) public;
          function destroy(address _from, uint256 _amount) public;
      }
      
      contract RING is DSToken("RING"), ERC223, ISmartToken {
          address public newOwner;
          bool public transfersEnabled = true;    // true if transfer/transferFrom are enabled, false if not
      
          uint256 public cap;
      
          address public controller;
      
          // allows execution only when transfers aren't disabled
          modifier transfersAllowed {
              assert(transfersEnabled);
              _;
          }
      
          constructor() public {
              setName("Evolution Land Global Token");
              controller = msg.sender;
          }
      
      //////////
      // IOwned Methods
      //////////
      
          /**
              @dev allows transferring the contract ownership
              the new owner still needs to accept the transfer
              can only be called by the contract owner
              @param _newOwner    new contract owner
          */
          function transferOwnership(address _newOwner) public auth {
              require(_newOwner != owner);
              newOwner = _newOwner;
          }
      
          /**
              @dev used by a new owner to accept an ownership transfer
          */
          function acceptOwnership() public {
              require(msg.sender == newOwner);
              owner = newOwner;
              newOwner = address(0);
          }
      
      //////////
      // SmartToken Methods
      //////////
          /**
              @dev disables/enables transfers
              can only be called by the contract owner
              @param _disable    true to disable transfers, false to enable them
          */
          function disableTransfers(bool _disable) public auth {
              transfersEnabled = !_disable;
          }
      
          function issue(address _to, uint256 _amount) public auth stoppable {
              mint(_to, _amount);
          }
      
          function destroy(address _from, uint256 _amount) public auth stoppable {
              // do not require allowance
      
              _balances[_from] = sub(_balances[_from], _amount);
              _supply = sub(_supply, _amount);
              emit Burn(_from, _amount);
              emit Transfer(_from, 0, _amount);
          }
      
      //////////
      // Cap Methods
      //////////
          function changeCap(uint256 _newCap) public auth {
              require(_newCap >= _supply);
      
              cap = _newCap;
          }
      
      //////////
      // Controller Methods
      //////////
          /// @notice Changes the controller of the contract
          /// @param _newController The new controller of the contract
          function changeController(address _newController) auth {
              controller = _newController;
          }
      
          /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
          ///  is approved by `_from`
          /// @param _from The address holding the tokens being transferred
          /// @param _to The address of the recipient
          /// @param _amount The amount of tokens to be transferred
          /// @return True if the transfer was successful
          function transferFrom(address _from, address _to, uint256 _amount
          ) public transfersAllowed returns (bool success) {
              // Alerts the token controller of the transfer
              if (isContract(controller)) {
                  if (!TokenController(controller).onTransfer(_from, _to, _amount))
                     revert();
              }
      
              success = super.transferFrom(_from, _to, _amount);
          }
      
          /*
           * ERC 223
           * Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
           */
          function transferFrom(address _from, address _to, uint256 _amount, bytes _data)
              public transfersAllowed
              returns (bool success)
          {
              // Alerts the token controller of the transfer
              if (isContract(controller)) {
                  if (!TokenController(controller).onTransfer(_from, _to, _amount))
                     revert();
              }
      
              require(super.transferFrom(_from, _to, _amount));
      
              if (isContract(_to)) {
                  ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
                  receiver.tokenFallback(_from, _amount, _data);
              }
      
              emit ERC223Transfer(_from, _to, _amount, _data);
      
              return true;
          }
      
          /*
           * ERC 223
           * Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
           * https://github.com/ethereum/EIPs/issues/223
           * function transfer(address _to, uint256 _value, bytes _data) public returns (bool success);
           */
          /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
          /// tokenFallback if sender is a contract.
          /// @dev Function that is called when a user or another contract wants to transfer funds.
          /// @param _to Address of token receiver.
          /// @param _amount Number of tokens to transfer.
          /// @param _data Data to be sent to tokenFallback
          /// @return Returns success of function call.
          function transfer(
              address _to,
              uint256 _amount,
              bytes _data)
              public
              returns (bool success)
          {
              return transferFrom(msg.sender, _to, _amount, _data);
          }
      
          /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
          ///  its behalf. This is a modified version of the ERC20 approve function
          ///  to be a little bit safer
          /// @param _spender The address of the account able to transfer the tokens
          /// @param _amount The amount of tokens to be approved for transfer
          /// @return True if the approval was successful
          function approve(address _spender, uint256 _amount) returns (bool success) {
              // Alerts the token controller of the approve function call
              if (isContract(controller)) {
                  if (!TokenController(controller).onApprove(msg.sender, _spender, _amount))
                      revert();
              }
              
              return super.approve(_spender, _amount);
          }
      
          function mint(address _guy, uint _wad) auth stoppable {
              require(add(_supply, _wad) <= cap);
      
              super.mint(_guy, _wad);
      
              emit Transfer(0, _guy, _wad);
          }
          function burn(address _guy, uint _wad) auth stoppable {
              super.burn(_guy, _wad);
      
              emit Transfer(_guy, 0, _wad);
          }
      
          /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
          ///  its behalf, and then a function is triggered in the contract that is
          ///  being approved, `_spender`. This allows users to use their tokens to
          ///  interact with contracts in one function call instead of two
          /// @param _spender The address of the contract able to transfer the tokens
          /// @param _amount The amount of tokens to be approved for transfer
          /// @return True if the function call was successful
          function approveAndCall(address _spender, uint256 _amount, bytes _extraData
          ) returns (bool success) {
              if (!approve(_spender, _amount)) revert();
      
              ApproveAndCallFallBack(_spender).receiveApproval(
                  msg.sender,
                  _amount,
                  this,
                  _extraData
              );
      
              return true;
          }
      
          /// @dev Internal function to determine if an address is a contract
          /// @param _addr The address being queried
          /// @return True if `_addr` is a contract
          function isContract(address _addr) constant internal returns(bool) {
              uint size;
              if (_addr == 0) return false;
              assembly {
                  size := extcodesize(_addr)
              }
              return size>0;
          }
      
          /// @notice The fallback function: If the contract's controller has not been
          ///  set to 0, then the `proxyPayment` method is called which relays the
          ///  ether and creates tokens as described in the token controller contract
          function ()  payable {
              if (isContract(controller)) {
                  if (! TokenController(controller).proxyPayment.value(msg.value)(msg.sender, msg.sig, msg.data))
                      revert();
              } else {
                  revert();
              }
          }
      
      //////////
      // Safety Methods
      //////////
      
          /// @notice This method can be used by the owner to extract mistakenly
          ///  sent tokens to this contract.
          /// @param _token The address of the token contract that you want to recover
          ///  set to 0 in case you want to extract ether.
          function claimTokens(address _token) public auth {
              if (_token == 0x0) {
                  address(msg.sender).transfer(address(this).balance);
                  return;
              }
      
              ERC20 token = ERC20(_token);
              uint balance = token.balanceOf(this);
              token.transfer(address(msg.sender), balance);
      
              emit ClaimedTokens(_token, address(msg.sender), balance);
          }
      
          function withdrawTokens(ERC20 _token, address _to, uint256 _amount) public auth
          {
              assert(_token.transfer(_to, _amount));
          }
      
      ////////////////
      // Events
      ////////////////
      
          event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
      }

      File 3 of 4: GringottsBank
      // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
      
      pragma solidity ^0.4.24;
      
      
      /**
       * @title ERC20Basic
       * @dev Simpler version of ERC20 interface
       * See https://github.com/ethereum/EIPs/issues/179
       */
      contract ERC20Basic {
        function totalSupply() public view returns (uint256);
        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);
      }
      
      // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
      
      pragma solidity ^0.4.24;
      
      
      
      /**
       * @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
        );
      }
      
      // File: @evolutionland/common/contracts/interfaces/ISettingsRegistry.sol
      
      pragma solidity ^0.4.24;
      
      contract ISettingsRegistry {
          enum SettingsValueTypes { NONE, UINT, STRING, ADDRESS, BYTES, BOOL, INT }
      
          function uintOf(bytes32 _propertyName) public view returns (uint256);
      
          function stringOf(bytes32 _propertyName) public view returns (string);
      
          function addressOf(bytes32 _propertyName) public view returns (address);
      
          function bytesOf(bytes32 _propertyName) public view returns (bytes);
      
          function boolOf(bytes32 _propertyName) public view returns (bool);
      
          function intOf(bytes32 _propertyName) public view returns (int);
      
          function setUintProperty(bytes32 _propertyName, uint _value) public;
      
          function setStringProperty(bytes32 _propertyName, string _value) public;
      
          function setAddressProperty(bytes32 _propertyName, address _value) public;
      
          function setBytesProperty(bytes32 _propertyName, bytes _value) public;
      
          function setBoolProperty(bytes32 _propertyName, bool _value) public;
      
          function setIntProperty(bytes32 _propertyName, int _value) public;
      
          function getValueTypeOf(bytes32 _propertyName) public view returns (uint /* SettingsValueTypes */ );
      
          event ChangeProperty(bytes32 indexed _propertyName, uint256 _type);
      }
      
      // File: @evolutionland/common/contracts/interfaces/IBurnableERC20.sol
      
      pragma solidity ^0.4.23;
      
      contract IBurnableERC20 {
          function burn(address _from, uint _value) public;
      }
      
      // File: @evolutionland/common/contracts/interfaces/IMintableERC20.sol
      
      pragma solidity ^0.4.23;
      
      contract IMintableERC20 {
      
          function mint(address _to, uint256 _value) public;
      }
      
      // File: @evolutionland/common/contracts/interfaces/IAuthority.sol
      
      pragma solidity ^0.4.24;
      
      contract IAuthority {
          function canCall(
              address src, address dst, bytes4 sig
          ) public view returns (bool);
      }
      
      // File: @evolutionland/common/contracts/DSAuth.sol
      
      pragma solidity ^0.4.24;
      
      
      contract DSAuthEvents {
          event LogSetAuthority (address indexed authority);
          event LogSetOwner     (address indexed owner);
      }
      
      /**
       * @title DSAuth
       * @dev The DSAuth contract is reference implement of https://github.com/dapphub/ds-auth
       * But in the isAuthorized method, the src from address(this) is remove for safty concern.
       */
      contract DSAuth is DSAuthEvents {
          IAuthority   public  authority;
          address      public  owner;
      
          constructor() public {
              owner = msg.sender;
              emit LogSetOwner(msg.sender);
          }
      
          function setOwner(address owner_)
              public
              auth
          {
              owner = owner_;
              emit LogSetOwner(owner);
          }
      
          function setAuthority(IAuthority authority_)
              public
              auth
          {
              authority = authority_;
              emit LogSetAuthority(authority);
          }
      
          modifier auth {
              require(isAuthorized(msg.sender, msg.sig));
              _;
          }
      
          modifier onlyOwner() {
              require(msg.sender == owner);
              _;
          }
      
          function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
              if (src == owner) {
                  return true;
              } else if (authority == IAuthority(0)) {
                  return false;
              } else {
                  return authority.canCall(src, this, sig);
              }
          }
      }
      
      // File: @evolutionland/common/contracts/SettingIds.sol
      
      pragma solidity ^0.4.24;
      
      /**
          Id definitions for SettingsRegistry.sol
          Can be used in conjunction with the settings registry to get properties
      */
      contract SettingIds {
          bytes32 public constant CONTRACT_RING_ERC20_TOKEN = "CONTRACT_RING_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_KTON_ERC20_TOKEN = "CONTRACT_KTON_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_GOLD_ERC20_TOKEN = "CONTRACT_GOLD_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_WOOD_ERC20_TOKEN = "CONTRACT_WOOD_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_WATER_ERC20_TOKEN = "CONTRACT_WATER_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_FIRE_ERC20_TOKEN = "CONTRACT_FIRE_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_SOIL_ERC20_TOKEN = "CONTRACT_SOIL_ERC20_TOKEN";
      
          bytes32 public constant CONTRACT_OBJECT_OWNERSHIP = "CONTRACT_OBJECT_OWNERSHIP";
      
          bytes32 public constant CONTRACT_TOKEN_LOCATION = "CONTRACT_TOKEN_LOCATION";
      
          bytes32 public constant CONTRACT_LAND_BASE = "CONTRACT_LAND_BASE";
      
          bytes32 public constant CONTRACT_USER_POINTS = "CONTRACT_USER_POINTS";
      
          bytes32 public constant CONTRACT_INTERSTELLAR_ENCODER = "CONTRACT_INTERSTELLAR_ENCODER";
      
          bytes32 public constant CONTRACT_DIVIDENDS_POOL = "CONTRACT_DIVIDENDS_POOL";
      
          bytes32 public constant CONTRACT_TOKEN_USE = "CONTRACT_TOKEN_USE";
      
          bytes32 public constant CONTRACT_REVENUE_POOL = "CONTRACT_REVENUE_POOL";
      
          bytes32 public constant CONTRACT_ERC721_BRIDGE = "CONTRACT_ERC721_BRIDGE";
      
          bytes32 public constant CONTRACT_PET_BASE = "CONTRACT_PET_BASE";
      
          // Cut owner takes on each auction, measured in basis points (1/100 of a percent).
          // this can be considered as transaction fee.
          // Values 0-10,000 map to 0%-100%
          // set ownerCut to 4%
          // ownerCut = 400;
          bytes32 public constant UINT_AUCTION_CUT = "UINT_AUCTION_CUT";  // Denominator is 10000
      
          bytes32 public constant UINT_TOKEN_OFFER_CUT = "UINT_TOKEN_OFFER_CUT";  // Denominator is 10000
      
          // Cut referer takes on each auction, measured in basis points (1/100 of a percent).
          // which cut from transaction fee.
          // Values 0-10,000 map to 0%-100%
          // set refererCut to 4%
          // refererCut = 400;
          bytes32 public constant UINT_REFERER_CUT = "UINT_REFERER_CUT";
      
          bytes32 public constant CONTRACT_LAND_RESOURCE = "CONTRACT_LAND_RESOURCE";
      }
      
      // File: contracts/BankSettingIds.sol
      
      pragma solidity ^0.4.24;
      
      
      
      contract BankSettingIds is SettingIds {
      
          // depositing X RING for 12 months, interest is about (1 * _unitInterest * X / 10**7) KTON
          // default: 1000
          bytes32 public constant UINT_BANK_UNIT_INTEREST = "UINT_BANK_UNIT_INTEREST";
      
          // penalty multiplier
          // default: 3
          bytes32 public constant UINT_BANK_PENALTY_MULTIPLIER = "UINT_BANK_PENALTY_MULTIPLIER";
      }
      
      // File: contracts/GringottsBankV2.sol
      
      pragma solidity ^0.4.24;
      
      
      
      
      
      
      
      contract  GringottsBank is DSAuth, BankSettingIds {
          /*
           *  Events
           */
          event ClaimedTokens(address indexed _token, address indexed _owner, uint _amount);
      
          event NewDeposit(uint256 indexed _depositID, address indexed _depositor, uint _value, uint _month, uint _interest);
      
          event ClaimedDeposit(uint256 indexed _depositID, address indexed _depositor, uint _value, bool isPenalty, uint penaltyAmount);
      
          event TransferDeposit(uint256 indexed _depositID, address indexed _oldDepositor, address indexed _newDepositor);
      
          event BurnAndRedeem(uint256 indexed _depositID,  address _depositor, uint48 _months, uint48 _startAt, uint64 _unitInterest, uint128 _value, bytes _data);
      
          /*
           *  Constants
           */
          uint public constant MONTH = 30 * 1 days;
      
          /*
           *  Structs
           */
          struct Deposit {
              address depositor;
              uint48 months; // Length of time from the deposit's beginning to end (in months), For now, months must >= 1 and <= 36
              uint48 startAt;   // when player deposit, timestamp in seconds
              uint128 value;  // amount of ring
              uint64 unitInterest;
              bool claimed;
          }
      
      
          /*
           *  Storages
           */
      
          bool private singletonLock = false;
      
      
          ISettingsRegistry public registry;
      
          mapping (uint256 => Deposit) public deposits;
      
          uint public depositCount;
      
          mapping (address => uint[]) public userDeposits;
      
          // player => totalDepositRING, total number of ring that the player has deposited
          mapping (address => uint256) public userTotalDeposit;
      
          /*
           *  Modifiers
           */
          modifier singletonLockCall() {
              require(!singletonLock, "Only can call once");
              _;
              singletonLock = true;
          }
      
          modifier canBeStoredWith128Bits(uint256 _value) {
              require(_value < 340282366920938463463374607431768211455);
              _;
          }
      
          modifier canBeStoredWith48Bits(uint256 _value) {
              require(_value < 281474976710656);
              _;
          }
      
      
          /**
           * @dev Bank's constructor which set the token address and unitInterest_
           */
          constructor () public {
              // initializeContract(_registry);
          }
      
          /**
           * @dev Same with constructor, but is used and called by storage proxy as logic contract.
           * @param _registry - address of SettingsRegistry
           */
          function initializeContract(address _registry) public singletonLockCall {
              // call Ownable's constructor
              owner = msg.sender;
      
              emit LogSetOwner(msg.sender);
      
              registry = ISettingsRegistry(_registry);
          }
      
          function getDeposit(uint _id) public view returns (address, uint128, uint128, uint256, uint256, bool ) {
              return (deposits[_id].depositor, deposits[_id].value, deposits[_id].months,
                  deposits[_id].startAt, deposits[_id].unitInterest, deposits[_id].claimed);
          }
      
          /**
           * @dev ERC223 fallback function, make sure to check the msg.sender is from target token contracts
           * @param _from - person who transfer token in for deposits or claim deposit with penalty KTON.
           * @param _amount - amount of token.
           * @param _data - data which indicate the operations.
           */
          function tokenFallback(address _from, uint256 _amount, bytes _data) public {
              address ring = registry.addressOf(SettingIds.CONTRACT_RING_ERC20_TOKEN);
              address kryptonite = registry.addressOf(SettingIds.CONTRACT_KTON_ERC20_TOKEN);
      
              // deposit entrance
              if(ring == msg.sender) {
                  uint months = bytesToUint256(_data);
                  _deposit(_from, _amount, months);
              }
              //  Early Redemption entrance
      
              if (kryptonite == msg.sender) {
                  uint _depositID = bytesToUint256(_data);
      
                  require(_amount >= computePenalty(_depositID), "No enough amount of KTON penalty.");
      
                  _claimDeposit(_from, _depositID, true, _amount);
      
                  // burn the KTON transferred in
                  IBurnableERC20(kryptonite).burn(address(this), _amount);
              }
          }
      
          /**
           * @dev transfer of deposit from  Ethereum network to Darwinia Network, params can be obtained by the function 'getDeposit'
           * @param _depositID - ID of deposit.
           * @param _data - receiving address of darwinia network.
      
           */
          function burnAndRedeem(uint256 _depositID, bytes _data) public {
              bytes32 darwiniaAddress;
      
              assembly {
                  let ptr := mload(0x40)
                  calldatacopy(ptr, 0, calldatasize)
                  darwiniaAddress := mload(add(ptr, 100))
              }
      
              // Check the validity of the deposit
              require(deposits[_depositID].claimed == false, "Already claimed");
              require(deposits[_depositID].startAt > 0, "Deposit not created.");
              require(deposits[_depositID].depositor == msg.sender, "Permission denied");
      
              require(_data.length == 32, "The address (Darwinia Network) must be in a 32 bytes hexadecimal format");
              require(darwiniaAddress != bytes32(0x0), "Darwinia Network Address can't be empty");
      
              removeUserDepositsByID(_depositID, msg.sender);
      
              require(deposits[_depositID].value <= userTotalDeposit[msg.sender], "Subtraction overflow");
              userTotalDeposit[msg.sender] -= deposits[_depositID].value;
      
              address ring = registry.addressOf(SettingIds.CONTRACT_RING_ERC20_TOKEN);
              IBurnableERC20(ring).burn(address(this), deposits[_depositID].value);
              
              emit BurnAndRedeem(
                  _depositID, 
                  deposits[_depositID].depositor, 
                  deposits[_depositID].months, 
                  deposits[_depositID].startAt, 
                  deposits[_depositID].unitInterest, 
                  deposits[_depositID].value, 
                  _data
              );
      
              delete deposits[_depositID];
          }
      
          /**
           * @dev Deposit for msg sender, require the token approvement ahead.
           * @param _amount - amount of token.
           * @param _months - the amount of months that the token will be locked in the deposit.
           */
          function deposit(uint256 _amount, uint256 _months) public {
              deposit(msg.sender, _amount, _months);
          }
      
          /**
           * @dev Deposit for benificiary, require the token approvement ahead.
           * @param _benificiary - benificiary of the deposit, which will get the KTON and RINGs after deposit being claimed.
           * @param _amount - amount of token.
           * @param _months - the amount of months that the token will be locked in the deposit.
           */
          function deposit(address _benificiary, uint256 _amount, uint256 _months) public {
      
              address ring = registry.addressOf(SettingIds.CONTRACT_RING_ERC20_TOKEN);
              require(ERC20(ring).transferFrom(msg.sender, address(this), _amount), "RING token tranfer failed.");
      
      
              _deposit(_benificiary, _amount, _months);
          }
      
          function claimDeposit(uint _depositID) public {
              _claimDeposit(msg.sender, _depositID, false, 0);
          }
      
          function claimDepositWithPenalty(uint _depositID) public {
              address kryptonite = ERC20(registry.addressOf(SettingIds.CONTRACT_KTON_ERC20_TOKEN));
              uint256 _penalty = computePenalty(_depositID);
      
              require(ERC20(kryptonite).transferFrom(msg.sender, address(this), _penalty));
      
              _claimDeposit(msg.sender, _depositID, true, _penalty);
      
              IBurnableERC20(kryptonite).burn(address(this), _penalty);
          }
      
          function transferDeposit(address _benificiary, uint _depositID) public {
              require(deposits[_depositID].depositor == msg.sender, "Depositor must be the msg.sender");
              require(_benificiary != 0x0, "Benificiary can not be zero");
              require(deposits[_depositID].claimed == false, "Already claimed, can not transfer.");
      
              // update the depositor of the deposit.
              deposits[_depositID].depositor = _benificiary;
      
              // update the deposit ids of the original user and new user.
              removeUserDepositsByID(_depositID, msg.sender);
              userDeposits[_benificiary].push(_depositID);
      
              // update the balance of the original depositor and new depositor.
              require(deposits[_depositID].value <= userTotalDeposit[msg.sender], "Subtraction overflow");
              userTotalDeposit[msg.sender] -= deposits[_depositID].value;
      
              userTotalDeposit[_benificiary] += deposits[_depositID].value;
              require(userTotalDeposit[_benificiary] >= deposits[_depositID].value, "Addition overflow");
      
              emit TransferDeposit(_depositID, msg.sender, _benificiary);
          }
      
          // normal Redemption, withdraw at maturity
          function _claimDeposit(address _depositor, uint _depositID, bool isPenalty, uint _penaltyAmount) internal {
      
              address ring = registry.addressOf(SettingIds.CONTRACT_RING_ERC20_TOKEN);
      
              require(deposits[_depositID].startAt > 0, "Deposit not created.");
              require(deposits[_depositID].claimed == false, "Already claimed");
              require(deposits[_depositID].depositor == _depositor, "Depositor must match.");
      
              if (isPenalty) {
                  require(now - deposits[_depositID].startAt < deposits[_depositID].months * MONTH );
              } else {
                  require(now - deposits[_depositID].startAt >= deposits[_depositID].months * MONTH );
              }
      
              deposits[_depositID].claimed = true;
              userTotalDeposit[_depositor] -= deposits[_depositID].value;
      
              require(ERC20(ring).transfer(_depositor, deposits[_depositID].value));
      
      
              emit ClaimedDeposit(_depositID, _depositor, deposits[_depositID].value, isPenalty, _penaltyAmount);
          }
      
          /**
           * @dev deposit actions
           * @param _depositor - person who deposits
           * @param _value - depositor wants to deposit how many tokens
           * @param _month - Length of time from the deposit's beginning to end (in months).
           */
      
          function _deposit(address _depositor, uint _value, uint _month)
              canBeStoredWith128Bits(_value) canBeStoredWith128Bits(_month) internal returns (uint _depositId) {
      
              address kryptonite = ERC20(registry.addressOf(SettingIds.CONTRACT_KTON_ERC20_TOKEN));
      
              require( _value > 0 );  // because the _value is pass in from token transfer, token transfer will help check, so there should not be overflow issues.
              require( _month <= 36 && _month >= 1 );
      
              _depositId = depositCount;
      
              uint64 _unitInterest = uint64(registry.uintOf(BankSettingIds.UINT_BANK_UNIT_INTEREST));
      
              deposits[_depositId] = Deposit({
                  depositor: _depositor,
                  value: uint128(_value),
                  months: uint48(_month),
                  startAt: uint48(now),
                  unitInterest: uint48(_unitInterest),
                  claimed: false
              });
      
              depositCount += 1;
      
              userDeposits[_depositor].push(_depositId);
      
              userTotalDeposit[_depositor] += _value;
              require(userTotalDeposit[_depositor] >= _value, "Addition overflow");
      
              // give the player interest immediately
              uint interest = computeInterest(_value, _month, _unitInterest);
              IMintableERC20(kryptonite).mint(_depositor, interest);
      
              emit NewDeposit(_depositId, _depositor, _value, _month, interest);
          }
      
          /**
           * @dev compute interst based on deposit amount and deposit time
           * @param _value - Amount of ring  (in deceimal units)
           * @param _month - Length of time from the deposit's beginning to end (in months).
           * @param _unitInterest - Parameter of basic interest for deposited RING.(default value is 1000, returns _unitInterest/ 10**7 for one year)
           */
          function computeInterest(uint _value, uint _month, uint _unitInterest)
              public canBeStoredWith128Bits(_value) canBeStoredWith48Bits(_month) pure returns (uint) {
              // these two actually mean the multiplier is 1.015
              uint numerator = 67 ** _month;
              uint denominator = 66 ** _month;
              uint quotient;
              uint remainder;
      
              assembly {
                  quotient := div(numerator, denominator)
                  remainder := mod(numerator, denominator)
              }
              // depositing X RING for 12 months, interest is about (1 * _unitInterest * X / 10**7) KTON
              // and the multiplier is about 3
              // ((quotient - 1) * 1000 + remainder * 1000 / denominator) is 197 when _month is 12.
              return (_unitInterest * uint128(_value)) * ((quotient - 1) * 1000 + remainder * 1000 / denominator) / (197 * 10**7);
          }
      
          function isClaimRequirePenalty(uint _depositID) public view returns (bool) {
              return (deposits[_depositID].startAt > 0 &&
                      !deposits[_depositID].claimed &&
                      (now - deposits[_depositID].startAt < deposits[_depositID].months * MONTH ));
          }
      
          function computePenalty(uint _depositID) public view returns (uint256) {
              require(isClaimRequirePenalty(_depositID), "Claim do not need Penalty.");
      
              uint256 monthsDuration = (now - deposits[_depositID].startAt) / MONTH;
      
              uint256 penalty = registry.uintOf(BankSettingIds.UINT_BANK_PENALTY_MULTIPLIER) *
                  (computeInterest(deposits[_depositID].value, deposits[_depositID].months, deposits[_depositID].unitInterest) - computeInterest(deposits[_depositID].value, monthsDuration, deposits[_depositID].unitInterest));
      
      
              return penalty;
          }
      
          function getDepositIds(address _user) public view returns(uint256[]) {
              return userDeposits[_user];
          }
      
          function bytesToUint256(bytes _encodedParam) public pure returns (uint256 a) {
              /* solium-disable-next-line security/no-inline-assembly */
              assembly {
                  a := mload(add(_encodedParam, /*BYTES_HEADER_SIZE*/32))
              }
          }
      
          /// @notice This method can be used by the owner to extract mistakenly
          ///  sent tokens to this contract.
          /// @param _token The address of the token contract that you want to recover
          ///  set to 0 in case you want to extract ether.
          function claimTokens(address _token) public onlyOwner {
              if (_token == 0x0) {
                  owner.transfer(address(this).balance);
                  return;
              }
              ERC20 token = ERC20(_token);
              uint balance = token.balanceOf(address(this));
              token.transfer(owner, balance);
      
              emit ClaimedTokens(_token, owner, balance);
          }
      
          function setRegistry(address _registry) public onlyOwner {
              registry = ISettingsRegistry(_registry);
          }
      
          function removeUserDepositsByID(uint _depositID, address _depositor) private{
              // update the deposit ids of the original user and new user.
              bool found = false;
              for(uint i = 0 ; i < userDeposits[_depositor].length; i++)
              {
                  if (!found && userDeposits[_depositor][i] == _depositID){
                      found = true;
                      delete userDeposits[_depositor][i];
                  }
      
                  if (found && i < userDeposits[_depositor].length - 1)
                  {
                      // shifts value to left
                      userDeposits[_depositor][i] =  userDeposits[_depositor][i+1];
                  }
              }
      
              delete userDeposits[_depositor][userDeposits[_depositor].length-1];
              //reducing the length
              userDeposits[_depositor].length--;
          }
      
      }

      File 4 of 4: SettingsRegistry
      // Dependency file: contracts/interfaces/ISettingsRegistry.sol
      
      // pragma solidity ^0.4.24;
      
      contract ISettingsRegistry {
          enum SettingsValueTypes { NONE, UINT, STRING, ADDRESS, BYTES, BOOL, INT }
      
          function uintOf(bytes32 _propertyName) public view returns (uint256);
      
          function stringOf(bytes32 _propertyName) public view returns (string);
      
          function addressOf(bytes32 _propertyName) public view returns (address);
      
          function bytesOf(bytes32 _propertyName) public view returns (bytes);
      
          function boolOf(bytes32 _propertyName) public view returns (bool);
      
          function intOf(bytes32 _propertyName) public view returns (int);
      
          function setUintProperty(bytes32 _propertyName, uint _value) public;
      
          function setStringProperty(bytes32 _propertyName, string _value) public;
      
          function setAddressProperty(bytes32 _propertyName, address _value) public;
      
          function setBytesProperty(bytes32 _propertyName, bytes _value) public;
      
          function setBoolProperty(bytes32 _propertyName, bool _value) public;
      
          function setIntProperty(bytes32 _propertyName, int _value) public;
      
          function getValueTypeOf(bytes32 _propertyName) public view returns (uint /* SettingsValueTypes */ );
      
          event ChangeProperty(bytes32 indexed _propertyName, uint256 _type);
      }
      
      // Dependency file: contracts/interfaces/IAuthority.sol
      
      // pragma solidity ^0.4.24;
      
      contract IAuthority {
          function canCall(
              address src, address dst, bytes4 sig
          ) public view returns (bool);
      }
      
      // Dependency file: contracts/DSAuth.sol
      
      // pragma solidity ^0.4.24;
      
      // import 'contracts/interfaces/IAuthority.sol';
      
      contract DSAuthEvents {
          event LogSetAuthority (address indexed authority);
          event LogSetOwner     (address indexed owner);
      }
      
      /**
       * @title DSAuth
       * @dev The DSAuth contract is reference implement of https://github.com/dapphub/ds-auth
       * But in the isAuthorized method, the src from address(this) is remove for safty concern.
       */
      contract DSAuth is DSAuthEvents {
          IAuthority   public  authority;
          address      public  owner;
      
          constructor() public {
              owner = msg.sender;
              emit LogSetOwner(msg.sender);
          }
      
          function setOwner(address owner_)
              public
              auth
          {
              owner = owner_;
              emit LogSetOwner(owner);
          }
      
          function setAuthority(IAuthority authority_)
              public
              auth
          {
              authority = authority_;
              emit LogSetAuthority(authority);
          }
      
          modifier auth {
              require(isAuthorized(msg.sender, msg.sig));
              _;
          }
      
          modifier onlyOwner() {
              require(msg.sender == owner);
              _;
          }
      
          function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
              if (src == owner) {
                  return true;
              } else if (authority == IAuthority(0)) {
                  return false;
              } else {
                  return authority.canCall(src, this, sig);
              }
          }
      }
      
      
      // Root file: contracts/SettingsRegistry.sol
      
      pragma solidity ^0.4.24;
      
      // import "contracts/interfaces/ISettingsRegistry.sol";
      // import "contracts/DSAuth.sol";
      
      /**
       * @title SettingsRegistry
       * @dev This contract holds all the settings for updating and querying.
       */
      contract SettingsRegistry is ISettingsRegistry, DSAuth {
      
          mapping(bytes32 => uint256) public uintProperties;
          mapping(bytes32 => string) public stringProperties;
          mapping(bytes32 => address) public addressProperties;
          mapping(bytes32 => bytes) public bytesProperties;
          mapping(bytes32 => bool) public boolProperties;
          mapping(bytes32 => int256) public intProperties;
      
          mapping(bytes32 => SettingsValueTypes) public valueTypes;
      
          function uintOf(bytes32 _propertyName) public view returns (uint256) {
              require(valueTypes[_propertyName] == SettingsValueTypes.UINT, "Property type does not match.");
              return uintProperties[_propertyName];
          }
      
          function stringOf(bytes32 _propertyName) public view returns (string) {
              require(valueTypes[_propertyName] == SettingsValueTypes.STRING, "Property type does not match.");
              return stringProperties[_propertyName];
          }
      
          function addressOf(bytes32 _propertyName) public view returns (address) {
              require(valueTypes[_propertyName] == SettingsValueTypes.ADDRESS, "Property type does not match.");
              return addressProperties[_propertyName];
          }
      
          function bytesOf(bytes32 _propertyName) public view returns (bytes) {
              require(valueTypes[_propertyName] == SettingsValueTypes.BYTES, "Property type does not match.");
              return bytesProperties[_propertyName];
          }
      
          function boolOf(bytes32 _propertyName) public view returns (bool) {
              require(valueTypes[_propertyName] == SettingsValueTypes.BOOL, "Property type does not match.");
              return boolProperties[_propertyName];
          }
      
          function intOf(bytes32 _propertyName) public view returns (int) {
              require(valueTypes[_propertyName] == SettingsValueTypes.INT, "Property type does not match.");
              return intProperties[_propertyName];
          }
      
          function setUintProperty(bytes32 _propertyName, uint _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.UINT, "Property type does not match.");
              uintProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.UINT;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.UINT));
          }
      
          function setStringProperty(bytes32 _propertyName, string _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.STRING, "Property type does not match.");
              stringProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.STRING;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.STRING));
          }
      
          function setAddressProperty(bytes32 _propertyName, address _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.ADDRESS, "Property type does not match.");
      
              addressProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.ADDRESS;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.ADDRESS));
          }
      
          function setBytesProperty(bytes32 _propertyName, bytes _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.BYTES, "Property type does not match.");
      
              bytesProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.BYTES;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.BYTES));
          }
      
          function setBoolProperty(bytes32 _propertyName, bool _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.BOOL, "Property type does not match.");
      
              boolProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.BOOL;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.BOOL));
          }
      
          function setIntProperty(bytes32 _propertyName, int _value) public auth {
              require(
                  valueTypes[_propertyName] == SettingsValueTypes.NONE || valueTypes[_propertyName] == SettingsValueTypes.INT, "Property type does not match.");
      
              intProperties[_propertyName] = _value;
              valueTypes[_propertyName] = SettingsValueTypes.INT;
      
              emit ChangeProperty(_propertyName, uint256(SettingsValueTypes.INT));
          }
      
          function getValueTypeOf(bytes32 _propertyName) public view returns (uint256 /* SettingsValueTypes */ ) {
              return uint256(valueTypes[_propertyName]);
          }
      
      }