Contract 0x8d1566569d5b695d44a9a234540f68d393cdc40d 2

 
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0x406c4c21b2c5a2cf09f1b05baab416170ce7f9085baafe94d2529cf860b295ecApprove407835302023-03-26 8:25:002 hrs 56 mins ago abuhafs12911.nft  IN  GameCredits: GAME Token0 MATIC0.001548402606 63.785895212
0xfdcb19b33bb101a553e81a3e66e2857d3ebf87f47abcf5bfb6468f6c04f0615bApprove407045852023-03-24 7:00:052 days 4 hrs ago0x54165d4ad082524a2354e98e571ad126c1d95dca IN  GameCredits: GAME Token0 MATIC0.005605432356 121.112122296
0xf1242894ef4f997375c1858121935a7a713a8b9f0e0a13daefa55a3f08d6f13aWithdraw406977812023-03-24 2:58:132 days 8 hrs ago0xd54e4f8a55247487dd7c8c59f14ee5c0c2889477 IN  GameCredits: GAME Token0 MATIC0.004430457125 132.779606365
0x37f4be988d67c9e4b71d3c17fcd3b503e70e7aa785802acc850aa1a6d83eedb3Withdraw406925962023-03-23 23:45:372 days 11 hrs ago0x65a8f07bd9a8598e1b5b6c0a88f4779dbc077675 IN  GameCredits: GAME Token0 MATIC0.014450784451 433.241926293
0x8d9d21e5697f82830521b5a14dc77dd8d54650dda121a3a1244ebf6773e36a8aApprove406859582023-03-23 19:41:322 days 15 hrs ago0x7f02ddcda68b5d6ca29c9954439a997fc464dbbf IN  GameCredits: GAME Token0 MATIC0.004536700174 97.439811309
0x836f61a812ca357a3e2b25f4fc5f9ba8d8f4d18db50141f193a4f67b797bbf25Approve406778332023-03-23 14:41:462 days 20 hrs ago0x72f422435a18fbe535979e3754c4a65b7708fa84 IN  GameCredits: GAME Token0 MATIC0.004336671655 93.143573866
0xb874130c6d4e646b7ba453a0d0c83e43ebad463b9b49bd8aeea456a2d189b7f9Transfer406673112023-03-23 7:52:473 days 3 hrs ago0x1f3bbca2b3e2432af649745288b368cd253444b2 IN  GameCredits: GAME Token0 MATIC0.005693981129103.681509327
0xd4522de15f84ae6952a63f787c6a55bc52c3e9eb8ba44cdf5b979a8347a562e8Approve406590082023-03-23 2:47:013 days 8 hrs ago0xff1153a6809fc384983963721b751b0df822e246 IN  GameCredits: GAME Token0 MATIC0.002519157447 95.527566173
0xe02def44fec49982694525495bf7504d7cefdb5803b0dc5a068f6cbcaf89daabApprove406589702023-03-23 2:45:393 days 8 hrs ago0xff1153a6809fc384983963721b751b0df822e246 IN  GameCredits: GAME Token0 MATIC0.006246585 135
0x52c9ec17cf9a47e344e8f9fac4514ee4269d986f3bfeba9ce0748cc5c1612a33Approve406589002023-03-23 2:42:073 days 8 hrs ago0xff1153a6809fc384983963721b751b0df822e246 IN  GameCredits: GAME Token0 MATIC0.003767474594 81.42194018
0x35f644fd80ae4ffebdbc086f8af1ede1b9c28deb53d9f4c66b1a044c066aaef9Approve406060712023-03-21 16:33:584 days 18 hrs ago0x40ac62d5aa80ceddab0de954c29bd62c75d514d2 IN  GameCredits: GAME Token0 MATIC0.007090678344 153.202652037
0x59b0ec1d4a6c5076dfc59827831ec43d70a11c76cbca4fc6cf1d88460d374f31Approve406033932023-03-21 14:38:414 days 20 hrs ago0xb4ea76d9488ed2e56feb5f803a9733d513cc9027 IN  GameCredits: GAME Token0 MATIC0.00850144997 350.214210927
0x3af5857f7c470920928647942dd6abfe63cc1656148500deca07651b70327491Approve405983862023-03-21 11:02:315 days 18 mins ago0xb4ea76d9488ed2e56feb5f803a9733d513cc9027 IN  GameCredits: GAME Token0 MATIC0.005065281028 208.662452248
0xdb8958930c1447d91c86c585d4d2258bc7cb4a3a061d5b7f43fad68e0c78a2aeApprove405983642023-03-21 11:01:435 days 19 mins ago0xb4ea76d9488ed2e56feb5f803a9733d513cc9027 IN  GameCredits: GAME Token0 MATIC0.006177853881 235.122887991
0x6cc258a1cffbe079a3955503528e27d8ec9f95fa4a7563b8f6fc2512b3e9ffa5Approve405981142023-03-21 10:50:515 days 30 mins ago tamimbinhamadalthani.dao  IN  GameCredits: GAME Token0 MATIC0.003630588514 149.560803874
0xba60e19b4b7c474ceebbdf85f514058d448986cc8844486cb360b2ab972d9390Approve405867262023-03-21 2:51:225 days 8 hrs ago0x93a2e114eae6b862f9dd53ad9642c9d81813f868 IN  GameCredits: GAME Token0 MATIC0.004960169227 106.535132362
0x003d869d2a2a3723a2ee25935641edb57dc110ee1950791492a6ee118b94e5cfApprove405745602023-03-20 18:13:445 days 17 hrs ago0x6859f18e80a0599ec2535f69a7dfd6077d7ee5e4 IN  GameCredits: GAME Token0 MATIC0.003301322979 135.996827184
0x253d3f4a34d7ad9db64420ceaa898bc9b127582f0a1f9a7c38f6be53e3e776f2Approve405696302023-03-20 15:05:145 days 20 hrs ago0x83952995ab3aebd284b8220dcdc72519ab435419 IN  GameCredits: GAME Token0 MATIC0.009650008922 207.264093356
0x00b8ac13293600a853fd23c596bfe605a64061e923d1bde8bdc5c0a044918724Withdraw405614042023-03-20 10:05:226 days 1 hr ago0x13556e5d0ce2b4ca2d42d0f64091d55c067f4910 IN  GameCredits: GAME Token0 MATIC0.00596781575 156.508241348
0xac545d571828e8791879cf815f0f4fb650a8ceee33863ee7b4884072a8492f25Withdraw405519542023-03-20 4:15:126 days 7 hrs ago0x65a8f07bd9a8598e1b5b6c0a88f4779dbc077675 IN  GameCredits: GAME Token0 MATIC0.015164127217 454.464807065
0x80fdf132fa0cf4226fad69ad22aa4254abd791c56890a5415682d555899fec89Withdraw405512022023-03-20 3:47:306 days 7 hrs ago0x65a8f07bd9a8598e1b5b6c0a88f4779dbc077675 IN  GameCredits: GAME Token0 MATIC0.015224022345 456.423994768
0xd567a8e7fb6256c1eae1903d1cd2fd248d0cc321249a9c35776fdb03531c6eddApprove405415292023-03-19 21:47:026 days 13 hrs ago olasquare27.nft  IN  GameCredits: GAME Token0 MATIC0.001658316363 68.313753391
0xa8deed97d173f211273e70d86464076dc2b6bc5768c50faaa06c67dce9dd0b62Withdraw405326882023-03-19 16:04:396 days 19 hrs ago0x0ebccfcbca6249c6dec4f2bd0ab47c034ec659fd IN  GameCredits: GAME Token0 MATIC0.004510139626 135.167669453
0x109ec1f66ef42e0e0bdc67094824398818afe30abd525976e636701c9c8f9d55Approve405114172023-03-19 2:19:597 days 9 hrs ago0x5c16a1799791acb83919e578707bf736bdfafefc IN  GameCredits: GAME Token0 MATIC0.003355716197 72.074490378
0x660147d9bd7f9aff9d2000ddf2e7f4f7d76efc867750f7a0f80326bab3809b04Transfer404330612023-03-17 1:39:279 days 9 hrs ago0x3ddb5044fa185e3aa568a7eaf82b1db57515b93e IN  GameCredits: GAME Token0 MATIC0.007815912212 142.350785207
[ Download CSV Export 

OVERVIEW

The GAME Credits platform provides a suite of tools for gaming, NFTs, and DeFi including the upcoming GENESIS Metaverse and the GAME Rewards Portal.

Latest 2 internal transactions
Parent Txn Hash Block From To Value
0x9bc08363ee2cce81b3a4e8080fcfae559074c76d168594be4abb767ae5e40852275496442022-04-25 7:07:09335 days 4 hrs ago 0x9d7dc4925885619c546b56e2698afef8fb37bc6c GameCredits: GAME Token0 MATIC
0x5920f17f7db22b278ba81dfb487796f493938f865bb38dbed4d5d7ba34265f44268563392022-04-07 15:25:39352 days 19 hrs ago Polygon: MATIC Token GameCredits: GAME Token5 MATIC
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GAME_ERC20

Compiler Version
v0.7.0+commit.9e61f92b

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at polygonscan.com on 2021-06-30
*/

pragma solidity ^0.7.0;
// SPDX-License-Identifier: UNLICENSED






/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
  /**
    * @dev Returns the addition of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
    *
    * - Addition cannot overflow.
    */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, "SafeMath: addition overflow");

    return c;
  }

  /**
    * @dev Returns the subtraction of two unsigned integers, reverting on
    * overflow (when the result is negative).
    *
    * Counterpart to Solidity's `-` operator.
    *
    * Requirements:
    *
    * - Subtraction cannot overflow.
    */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, "SafeMath: subtraction overflow");
  }

  /**
    * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
    * overflow (when the result is negative).
    *
    * Counterpart to Solidity's `-` operator.
    *
    * Requirements:
    *
    * - Subtraction cannot overflow.
    */
  function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }

  /**
    * @dev Returns the multiplication of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `*` operator.
    *
    * Requirements:
    *
    * - Multiplication cannot overflow.
    */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
  }

  /**
    * @dev Returns the integer division of two unsigned integers. Reverts on
    * division by zero. The result is rounded towards zero.
    *
    * Counterpart to Solidity's `/` operator. Note: this function uses a
    * `revert` opcode (which leaves remaining gas untouched) while Solidity
    * uses an invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    *
    * - The divisor cannot be zero.
    */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, "SafeMath: division by zero");
  }

  /**
    * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
    * division by zero. The result is rounded towards zero.
    *
    * Counterpart to Solidity's `/` operator. Note: this function uses a
    * `revert` opcode (which leaves remaining gas untouched) while Solidity
    * uses an invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    *
    * - The divisor cannot be zero.
    */
  function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
    * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
    * Reverts when dividing by zero.
    *
    * Counterpart to Solidity's `%` operator. This function uses a `revert`
    * opcode (which leaves remaining gas untouched) while Solidity uses an
    * invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    *
    * - The divisor cannot be zero.
    */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, "SafeMath: modulo by zero");
  }

  /**
    * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
    * Reverts with custom message when dividing by zero.
    *
    * Counterpart to Solidity's `%` operator. This function uses a `revert`
    * opcode (which leaves remaining gas untouched) while Solidity uses an
    * invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    *
    * - The divisor cannot be zero.
    */
  function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}


abstract contract EIP712Base {
  struct EIP712Domain {
    string name;
    string version;
    uint256 chainId;
    address verifyingContract;
  }

  bytes32 public constant EIP712_DOMAIN_TYPEHASH = keccak256(
    bytes(
      "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
    )
  );
  bytes32 internal domainSeperator;
  bytes32 internal workerDomainSeperator;

  constructor(
      string memory name,
      string memory version
  ) {
    domainSeperator = encodeDomainSeperator(name, version);
    workerDomainSeperator = encodeWorkerDomainSeperator(name, version);
  }

  function getChainId() public pure returns (uint256) {
    uint256 id;
    assembly {
      id := chainid()
    }
    return id;
  }

  function getDomainSeperator() public view returns (bytes32) {
    return domainSeperator;
  }

  function getWorkerDomainSeperator() public view returns (bytes32) {
    return workerDomainSeperator;
  }

  function encodeDomainSeperator(string memory name, string memory version) public view returns (bytes32) {
    uint chainId = getChainId();
    require(chainId != 0, "chain ID must not be zero");
    return keccak256(
      abi.encode(
        EIP712_DOMAIN_TYPEHASH,
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainId,
        address(this)
      )
    );
  }

  // This encodes the domain separator to the root chain, rather than the main chain.
  function encodeWorkerDomainSeperator(string memory name, string memory version) public view returns (bytes32) {
    uint chainId = getChainId();

    // 1 == truffle test; 1 == Ethereum
    // 137 == matic mainnet; 1 == Ethereum
    // 80001 == matic mumbai; 5 == Goerli
    chainId = chainId == 137 || chainId == 1 ? 1 : chainId == 80001 ? 5 : 0;
    require(chainId != 0, "chain ID must not be zero");
    return keccak256(
      abi.encode(
        EIP712_DOMAIN_TYPEHASH,
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainId,
        address(this)
      )
    );
  }

  /**
    * Accept message hash and returns hash message in EIP712 compatible form
    * So that it can be used to recover signer from signature signed using EIP712 formatted data
    * https://eips.ethereum.org/EIPS/eip-712
    * "\\x19" makes the encoding deterministic
    * "\\x01" is the version byte to make it compatible to EIP-191
    */
  function toTypedMessageHash(bytes32 messageHash)
    internal
    view
    returns (bytes32)
  {
    return
      keccak256(
        abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash)
      );
  }
}


/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {

  function _msgSender()
    internal
    virtual
    view
    returns (address payable sender)
  {
    if (msg.sender == address(this)) {
      bytes memory array = msg.data;
      uint256 index = msg.data.length;
      assembly {
        // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
        sender := and(
            mload(add(array, index)),
            0xffffffffffffffffffffffffffffffffffffffff
        )
      }
    } else {
      sender = msg.sender;
    }
    return sender;
  }

  function _msgData() internal view virtual returns (bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
  }
}



/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface iERC20 {
  /**
    * @dev Returns the amount of tokens in existence.
    */
  function totalSupply() external view returns (uint256);

  /**
    * @dev Returns the amount of tokens owned by `account`.
    */
  function balanceOf(address account) external view returns (uint256);

  /**
    * @dev Moves `amount` tokens from the caller's account to `recipient`.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * Emits a {Transfer} event.
    */
  function transfer(address recipient, uint256 amount) external returns (bool);

  /**
    * @dev Returns the remaining number of tokens that `spender` will be
    * allowed to spend on behalf of `owner` through {transferFrom}. This is
    * zero by default.
    *
    * This value changes when {approve} or {transferFrom} are called.
    */
  function allowance(address owner, address spender) external view returns (uint256);

  /**
    * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * IMPORTANT: 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
    *
    * Emits an {Approval} event.
    */
  function approve(address spender, uint256 amount) external returns (bool);

  /**
    * @dev Moves `amount` tokens from `sender` to `recipient` using the
    * allowance mechanism. `amount` is then deducted from the caller's
    * allowance.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * Emits a {Transfer} event.
    */
  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

  /**
    * @dev Emitted when `value` tokens are moved from one account (`from`) to
    * another (`to`).
    *
    * Note that `value` may be zero.
    */
  event Transfer(address indexed from, address indexed to, uint256 value);

  /**
    * @dev Emitted when the allowance of a `spender` for an `owner` is set by
    * a call to {approve}. `value` is the new allowance.
    */
  event Approval(address indexed owner, address indexed spender, uint256 value);
}



/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
abstract contract ERC20 is Context, iERC20 {
  using SafeMath for uint256;
  using Address for address;

  mapping (address => uint256) internal _balances;

  mapping (address => mapping (address => uint256)) private _allowances;

  uint256 private _totalSupply;

  string private _name;
  string private _symbol;
  uint8 private _decimals;

  /**
    * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
    * a default value of 18.
    *
    * To select a different value for {decimals}, use {_setupDecimals}.
    *
    * All three of these values are immutable: they can only be set once during
    * construction.
    */
  constructor (string memory name, string memory symbol) {
    _name = name;
    _symbol = symbol;
    _decimals = 18;
  }

  /**
    * @dev Returns the name of the token.
    */
  function name() public view returns (string memory) {
    return _name;
  }

  /**
    * @dev Returns the symbol of the token, usually a shorter version of the
    * name.
    */
  function symbol() public view returns (string memory) {
    return _symbol;
  }

  /**
    * @dev Returns the number of decimals used to get its user representation.
    * For example, if `decimals` equals `2`, a balance of `505` tokens should
    * be displayed to a user as `5,05` (`505 / 10 ** 2`).
    *
    * Tokens usually opt for a value of 18, imitating the relationship between
    * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
    * called.
    *
    * NOTE: This information is only used for _display_ purposes: it in
    * no way affects any of the arithmetic of the contract, including
    * {IERC20-balanceOf} and {IERC20-transfer}.
    */
  function decimals() public view returns (uint8) {
    return _decimals;
  }

  /**
    * @dev See {IERC20-totalSupply}.
    */
  function totalSupply() public view override returns (uint256) {
    return _totalSupply;
  }

  /**
    * @dev See {IERC20-balanceOf}.
    */
  function balanceOf(address account) public view override returns (uint256) {
    return _balances[account];
  }

  /**
    * @dev See {IERC20-transfer}.
    *
    * Requirements:
    *
    * - `recipient` cannot be the zero address.
    * - the caller must have a balance of at least `amount`.
    */
  function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
    _transfer(_msgSender(), recipient, amount);
    return true;
  }

  /**
    * @dev See {IERC20-allowance}.
    */
  function allowance(address owner, address spender) public view virtual override returns (uint256) {
    return _allowances[owner][spender];
  }

  /**
    * @dev See {IERC20-approve}.
    *
    * Requirements:
    *
    * - `spender` cannot be the zero address.
    */
  function approve(address spender, uint256 amount) public virtual override returns (bool) {
    _approve(_msgSender(), spender, amount);
    return true;
  }

  /**
    * @dev See {IERC20-transferFrom}.
    *
    * Emits an {Approval} event indicating the updated allowance. This is not
    * required by the EIP. See the note at the beginning of {ERC20};
    *
    * Requirements:
    * - `sender` and `recipient` cannot be the zero address.
    * - `sender` must have a balance of at least `amount`.
    * - the caller must have allowance for ``sender``'s tokens of at least
    * `amount`.
    */
  function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
    _transfer(sender, recipient, amount);
    _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
    return true;
  }

  /**
    * @dev Atomically increases the allowance granted to `spender` by the caller.
    *
    * This is an alternative to {approve} that can be used as a mitigation for
    * problems described in {IERC20-approve}.
    *
    * Emits an {Approval} event indicating the updated allowance.
    *
    * Requirements:
    *
    * - `spender` cannot be the zero address.
    */
  function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
    _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
    return true;
  }

  /**
    * @dev Atomically decreases the allowance granted to `spender` by the caller.
    *
    * This is an alternative to {approve} that can be used as a mitigation for
    * problems described in {IERC20-approve}.
    *
    * Emits an {Approval} event indicating the updated allowance.
    *
    * Requirements:
    *
    * - `spender` cannot be the zero address.
    * - `spender` must have allowance for the caller of at least
    * `subtractedValue`.
    */
  function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
    _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
    return true;
  }

  /**
    * @dev Moves tokens `amount` from `sender` to `recipient`.
    *
    * This is internal function is equivalent to {transfer}, and can be used to
    * e.g. implement automatic token fees, slashing mechanisms, etc.
    *
    * Emits a {Transfer} event.
    *
    * Requirements:
    *
    * - `sender` cannot be the zero address.
    * - `recipient` cannot be the zero address.
    * - `sender` must have a balance of at least `amount`.
    */
  function _transfer(address sender, address recipient, uint256 amount) internal virtual {
    require(sender != address(0), "ERC20: transfer from the zero address");
    require(recipient != address(0), "ERC20: transfer to the zero address");

    _beforeTokenTransfer(sender, recipient, amount);

    _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
    _balances[recipient] = _balances[recipient].add(amount);
    emit Transfer(sender, recipient, amount);
  }

  /** @dev Creates `amount` tokens and assigns them to `account`, increasing
    * the total supply.
    *
    * Emits a {Transfer} event with `from` set to the zero address.
    *
    * Requirements
    *
    * - `to` cannot be the zero address.
    */
  function _mint(address account, uint256 amount) internal virtual {
    require(account != address(0), "ERC20: mint to the zero address");

    _beforeTokenTransfer(address(0), account, amount);

    _totalSupply = _totalSupply.add(amount);
    _balances[account] = _balances[account].add(amount);
    emit Transfer(address(0), account, amount);
  }

  /**
    * @dev Destroys `amount` tokens from `account`, reducing the
    * total supply.
    *
    * Emits a {Transfer} event with `to` set to the zero address.
    *
    * Requirements
    *
    * - `account` cannot be the zero address.
    * - `account` must have at least `amount` tokens.
    */
  function _burn(address account, uint256 amount) internal virtual {
    require(account != address(0), "ERC20: burn from the zero address");

    _beforeTokenTransfer(account, address(0), amount);

    _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
    _totalSupply = _totalSupply.sub(amount);
    emit Transfer(account, address(0), amount);
  }

  /**
    * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
    *
    * This internal function is equivalent to `approve`, and can be used to
    * e.g. set automatic allowances for certain subsystems, etc.
    *
    * Emits an {Approval} event.
    *
    * Requirements:
    *
    * - `owner` cannot be the zero address.
    * - `spender` cannot be the zero address.
    */
  function _approve(address owner, address spender, uint256 amount) internal virtual {
    require(owner != address(0), "ERC20: approve from the zero address");
    require(spender != address(0), "ERC20: approve to the zero address");

    _allowances[owner][spender] = amount;
    emit Approval(owner, spender, amount);
  }

  /**
    * @dev Sets {decimals} to a value other than the default one of 18.
    *
    * WARNING: This function should only be called from the constructor. Most
    * applications that interact with token contracts will not expect
    * {decimals} to ever change, and may work incorrectly if it does.
    */
  function _setupDecimals(uint8 decimals_) internal {
    _decimals = decimals_;
  }

  /**
    * @dev Hook that is called before any transfer of tokens. This includes
    * minting and burning.
    *
    * Calling conditions:
    *
    * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
    * will be to transferred to `to`.
    * - when `from` is zero, `amount` tokens will be minted for `to`.
    * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
    * - `from` and `to` are never both zero.
    *
    * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
    */
  function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}



interface iChildToken {
    function deposit(address user, bytes calldata depositData) external;
}



abstract contract NetworkAgnostic is EIP712Base, Context {
  using SafeMath for uint256;
  bytes32 internal constant META_TRANSACTION_TYPEHASH = keccak256(
    bytes(
      "MetaTransaction(uint256 nonce,address from,bytes functionSignature)"
    )
  );
  event MetaTransactionExecuted(
    address userAddress,
    address payable relayerAddress,
    bytes functionSignature
  );
  mapping(address => uint256) nonces;

  /*
    * Meta transaction structure.
    * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
    * He should call the desired function directly in that case.
    */
  struct MetaTransaction {
    uint256 nonce;
    address from;
    bytes functionSignature;
  }

  constructor(
    string memory name,
    string memory version
  ) EIP712Base(name, version) {}

  function executeMetaTransaction(
    address userAddress,
    bytes memory functionSignature,
    bytes32 sigR,
    bytes32 sigS,
    uint8 sigV
  ) public payable returns (bytes memory) {
    MetaTransaction memory metaTx = MetaTransaction({
      nonce: nonces[userAddress],
      from: userAddress,
      functionSignature: functionSignature
    });

    require(
      verify(userAddress, metaTx, sigR, sigS, sigV),
      "Signer and signature do not match"
    );

    // increase nonce for user (to avoid re-use)
    nonces[userAddress] = nonces[userAddress].add(1);

    emit MetaTransactionExecuted(
      userAddress,
      msg.sender,
      functionSignature
    );

    // Append userAddress and relayer address at the end to extract it from calling context
    (bool success, bytes memory returnData) = address(this).call(
      abi.encodePacked(functionSignature, userAddress)
    );
    require(success, "Function call not successful");

    return returnData;
  }

  function hashMetaTransaction(MetaTransaction memory metaTx)
    internal
    pure
    returns (bytes32)
  {
    return
      keccak256(
        abi.encode(
          META_TRANSACTION_TYPEHASH,
          metaTx.nonce,
          metaTx.from,
          keccak256(metaTx.functionSignature)
        )
      );
  }

  function getNonce(address user) public view returns (uint256 nonce) {
    nonce = nonces[user];
  }

  function verify(
    address signer,
    MetaTransaction memory metaTx,
    bytes32 sigR,
    bytes32 sigS,
    uint8 sigV
  ) internal view returns (bool) {
    return
      signer != address(0) && signer ==
      ecrecover(
        toTypedMessageHash(hashMetaTransaction(metaTx)),
        sigV,
        sigR,
        sigS
      );
  }
}




// @title iLocalContract
// @dev The interface for the main Token Manager contract
//  Only methods required for calling by sibling contracts are required here
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract iLocalContract {

  function updateLocalContract(address contract_, bool isLocal_) virtual external;

  function metaTxSenderIsWorkerOrMinion() internal virtual returns (bool);

  function isLocalContract()
    external
    virtual
    pure
  returns(bool) {
    return true;
  }
}

abstract contract WorkerMetaTransactions is NetworkAgnostic, iLocalContract {
  using SafeMath for uint256;
  bytes32 private constant WORKER_META_TRANSACTION_TYPEHASH = keccak256(
    bytes(
      "WorkerMetaTransaction(bytes32 replayPrevention,address from,bytes functionSignature)"
    )
  );

  // This mapping records all meta-transactions that have been played.
  // It costs more than the nonce method, but this is permissioned, so it's more reliable.
  mapping(address => mapping(bytes32 => bool)) playedTransactions;

  /*
    * Meta transaction structure.
    * No point of including value field here as a user who is doing value transfer has the funds to pay for gas
    *   and should call the desired function directly in that case.
    */
  struct WorkerMetaTransaction {
    bytes32 replayPrevention;
    address from;
    bytes functionSignature;
  }

  function workerExecuteMetaTransaction(
    address userAddress_,
    bytes32 replayPrevention_,
    bytes memory functionSignature_,
    bytes32 sigR_,
    bytes32 sigS_,
    uint8 sigV_
  )
    public
    payable
  returns (bytes memory) {
    require(metaTxSenderIsWorkerOrMinion(), "Worker Meta-Transaction sent by account other than a worker/minion");
    WorkerMetaTransaction memory metaTx = WorkerMetaTransaction({
      replayPrevention: replayPrevention_,
      from: userAddress_,
      functionSignature: functionSignature_
    });

    require(
      workerVerify(userAddress_, metaTx, sigR_, sigS_, sigV_),
      "Signer and signature do not match"
    );

    require(playedTransactions[userAddress_][replayPrevention_] == false, "REPLAY of a previous transaction");
    playedTransactions[userAddress_][replayPrevention_] = true;

    emit MetaTransactionExecuted(
      userAddress_,
      msg.sender,
      functionSignature_
    );

    // Append userAddress and relayer address at the end to extract it from calling context
    (bool success, bytes memory returnData) = address(this).call(
      abi.encodePacked(functionSignature_, userAddress_)
    );
    require(success, "Function call not successful");

    return returnData;
  }

  function hashWorkerMetaTransaction(WorkerMetaTransaction memory metaTx_)
    internal
    pure
  returns (bytes32) {
    return
      keccak256(
        abi.encode(
          WORKER_META_TRANSACTION_TYPEHASH,
          metaTx_.replayPrevention,
          metaTx_.from,
          keccak256(metaTx_.functionSignature)
        )
      );
  }

  function workerVerify(
    address signer_,
    WorkerMetaTransaction memory metaTx_,
    bytes32 sigR_,
    bytes32 sigS_,
    uint8 sigV_
  ) 
    internal
    view
  returns (bool) {
    return
      signer_ != address(0) && signer_ ==
      ecrecover(
        toWorkerTypedMessageHash(hashWorkerMetaTransaction(metaTx_)),
        sigV_,
        sigR_,
        sigS_
      );
  }

  /**
    * Accept message hash and returns hash message in EIP712 compatible form
    * So that it can be used to recover signer from signature signed using EIP712 formatted data
    * https://eips.ethereum.org/EIPS/eip-712
    * "\\x19" makes the encoding deterministic
    * "\\x01" is the version byte to make it compatible to EIP-191
    */
  function toWorkerTypedMessageHash(bytes32 messageHash_)
    internal
    view
    returns (bytes32)
  {
    return
      keccak256(
        abi.encodePacked("\x19\x01", getWorkerDomainSeperator(), messageHash_)
      );
  }
}



abstract contract ChildERC20 is ERC20, iChildToken, WorkerMetaTransactions {

  address public depositor;

  constructor(
    string memory name_,
    string memory symbol_,
    uint8 decimals_,
    address depositor_
  ) ERC20(name_, symbol_) {
    _setupDecimals(decimals_);
    depositor = depositor_;
  }

  modifier onlyDepositor() {
    require(_msgSender() == depositor, "ChildERC20: INSUFFICIENT_PERMISSIONS");
    _;
  }

  function _setDepositor(address _depositor)
    internal
  {
    depositor = _depositor;
  }

  /**
    * @notice called when token is deposited on root chain
    * @dev Should be callable only by ChildChainManager
    * Should handle deposit by minting the required amount for user
    * Make sure minting is done only by this function
    * @param user user address for whom deposit is being done
    * @param depositData abi encoded amount
    */
  function deposit(address user, bytes calldata depositData)
    external
    override
    onlyDepositor
  {
    uint256 amount = abi.decode(depositData, (uint256));
    _mint(user, amount);
  }

  /**
    * @notice called when user wants to withdraw tokens back to root chain
    * @dev Should burn user's tokens. This transaction will be verified when exiting on root chain
    * @param amount amount of tokens to withdraw
    */
  function withdraw(uint256 amount) external {
    _burn(_msgSender(), amount);
  }

  // To recieve ether in contract
  receive() external payable {}
}



// @title iGAME_Game
// @dev The interface for the GAME Credits Game Data contract
//  Only methods required for calling by sibling contracts are required here
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract iGAME_Game {
  mapping(uint => mapping(address => bool)) public gameAdmins;
  mapping(uint => mapping(address => bool)) public gameOperators;

  function getCardPrice(uint game_, uint set_, uint card_) virtual external view returns(uint256);
  function getCardLoyaltyPrice(uint game_, uint set_, uint card_) virtual external view returns(uint256);
  function isGameAdmin(uint game_, address admin_) virtual external view returns(bool);
  function linkContracts(address erc721Contract_, address erc20Contract_) virtual external;
  function isOperatorOrMinion(uint game_, address sender_) virtual external returns(bool);
  function isValidCaller(address account_, bool isMinion_, uint game_) virtual external view returns(bool isValid);
  function burnToken(uint tokenId_) virtual external;
  function createTokenFromCard(uint game_, uint set_, uint card_) virtual external returns(uint tokenId, uint tradeLockTime, uint fixedXp);
}



// @title iGAME_Master
// @dev The interface for the Master contract
//  Only methods required for calling by sibling contracts are required here
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract iGAME_Master {
  function isOwner(address owner_) virtual external view returns (bool);
  function isCFO(address cfo_) virtual external view returns (bool);
  function isCOO(address coo_) virtual external view returns (bool);
  function isWorker(address account_) virtual external view returns (bool);
  function isWorkerOrMinion(address account_) virtual external view returns (bool);
  function makeFundedCall(address account_) virtual external returns (bool);
  function updateCollectibleSaleStatus(uint game_, uint card_, bool isOnSale_) virtual external;

  function isMaster()
    external
    pure
  returns(bool) {
    return true;
  }
}



// @title iGAME_ERC721
// @dev The interface for the main Token Manager contract
//  Only methods required for calling by sibling contracts are required here
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract iGAME_ERC721 {

  function auctionTransfer(address from_, address to_, uint tokenId_) virtual external;

  function inGameOwnerOf(uint tokenId_) virtual external view returns (bytes32 owner_);

  function revokeToken(uint game_, uint tokenId_, bytes32 purchaseId_)
    virtual external returns (bool _isRevoked);

  function transferNewToken(bytes32 recipient_, uint tokenId_, uint tradeLockTime_)
    virtual external;

  function getCryptoAccount(uint game_, bytes32 inGameAccount_)
    virtual public view returns(address cryptoAccount);

  function getValidCryptoAccount(uint game_, bytes32 inGameAccount_)
    virtual public view returns(address cryptoAccount);

  function getInGameAccount(uint game_, address cryptoAccount_)
    virtual public view returns(bytes32 inGameAccount);

  function getValidInGameAccount(uint game_, address cryptoAccount_)
    virtual public view returns(bytes32 inGameAccount);

  function getOrCreateInGameAccount(uint game_, address cryptoAccount_)
    virtual external returns(bytes32 inGameAccount);

  function linkContracts(address gameContract_, address erc20Contract_) virtual external;

  function generateCollectible(uint tokenId_, uint xp_, uint xpPerHour_, uint creationTime_) virtual external;
}



// @title iGAME_ERC20
// @dev The interface for the Auction & ERC-20 contract
//  Only methods required for calling by sibling contracts are required here
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract iGAME_ERC20 {

  function cancelAuctionByManager(uint tokenId_) virtual external;

  function transferByContract(address from_, address to_, uint256 value_) virtual external;

  function linkContracts(address gameContract_, address erc721Contract_) virtual external;

  function getGameBalance(uint game_) virtual public view returns(uint balance);

  function getLoyaltyPointsGranted(uint game_, address account_) virtual public view returns(uint currentPoints);

  function getLoyaltyPointSpends(uint game_, address account_) virtual public view returns(uint currentPoints);

  function getLoyaltyPointsTotal(uint game_, address account_) virtual public view returns(uint currentPoints);

  function thirdPartySpendLoyaltyPoints(uint game_, address account_, uint pointsToSpend_) virtual external;
}


// @title ERC20 Sidechain manager imlpementation
// @dev Utility contract that manages Ethereum and ERC-20 tokens transferred in from the main chain
// @dev Can manage any number of tokens
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract GAME_ERC20Access is iGAME_ERC20, ChildERC20 {
  using SafeMath for uint256;

  event Balance(address account, uint256 value);

  iGAME_Master public masterContract;
  iGAME_Game public gameContract;
  iGAME_ERC721 public erc721Contract;
  mapping(address => bool) public localContracts;

  // Tracks contracts that are allowed to spend Loyalty Points
  mapping(address => bool) public approvedLoyaltySpenders;

  event ThirdPartyRewwardsSpender(address indexed spenderContract, bool isSpender);

  constructor(address masterContract_)
  {
    masterContract = iGAME_Master(masterContract_);
    localContracts[masterContract_] = true;
  }


  modifier workerOrMinion() {
    require(masterContract.makeFundedCall(_msgSender()), "must be called by a worker or minion");
    _;
  }

  modifier onlyCFO() {
    require(masterContract.isCFO(_msgSender()), "sender must be the cfo");
    _;
  }

  modifier onlyOwner() {
    require(masterContract.isOwner(_msgSender()), "sender must be the owner");
    _;
  }

  modifier onlyGameAdmin(uint game_) {
    require(gameContract.isGameAdmin(game_, _msgSender()), "sender must be a game admin");
    _;
  }

  modifier onlyLocalContract() {
    // Cannot be called using native meta-transactions
    require(localContracts[msg.sender], "must be called by a local contract");
    _;
  }

  function updateLocalContract(address contract_, bool isLocal_)
    external
    override
    onlyLocalContract
  {
    require(contract_ != address(masterContract), "can't reset the master contract");
    require(contract_ != address(erc721Contract), "can't reset the erc721 contract");
    require(contract_ != address(0), "can't be the zero address");
    localContracts[contract_] = isLocal_;
  }

  function linkContracts(address gameContract_, address erc721Contract_)
    external
    override
    onlyLocalContract
  {
    require(address(gameContract) == address(0), "token contract must be blank");
    require(address(erc721Contract) == address(0), "token contract must be blank");
    gameContract = iGAME_Game(gameContract_);
    erc721Contract = iGAME_ERC721(erc721Contract_);

    approvedLoyaltySpenders[gameContract_] = true;
    emit ThirdPartyRewwardsSpender(gameContract_, true);
    approvedLoyaltySpenders[erc721Contract_] = true;
    emit ThirdPartyRewwardsSpender(erc721Contract_, true);
    approvedLoyaltySpenders[address(masterContract)] = true;
    emit ThirdPartyRewwardsSpender(address(masterContract), true);
  }

  function setDepositor(address depositor_)
    external
    onlyOwner
  {
    _setDepositor(depositor_);
  }

  function transferByContract(address from_, address to_, uint256 value_)
    external
    override
    onlyLocalContract
  {
    _transfer(from_, to_, value_);
  }

  function metaTxSenderIsWorkerOrMinion()
    internal
    override
  returns (bool) {
    return masterContract.makeFundedCall(msg.sender);
  }
}

// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract GAME_ERC20Loyalty is GAME_ERC20Access {
  using SafeMath for uint256;

  // Emitted whenever a user's stake is increased or decreased.
  event LoyaltyPointsChange(
    uint indexed game,
    address indexed account,
    uint indexed week,
    uint currentStake,
    uint totalGranted,
    uint totalSpent
  );
  event LoyaltyPointsGranted(uint indexed game, address indexed account, uint pointsGrant);
  event LoyaltyPointsRemoved(uint indexed game, address indexed account, uint pointsRemoved);
  event LoyaltyPartnerSet(uint indexed game, address indexed account, uint week);

  // GAME stake needed to gain one Loyalty Point, per week (10 ** 18 is 1 GAME)
  uint public gcPerLoyaltyPoint = 10 ** 18;

  uint public constant WEEK_ZERO_START = 1538352000; // 10/1/2018 @ 00:00:00
  uint public constant SECONDS_PER_WEEK = 604800;

  // Granted by the account stake amount; can also be granted
  mapping(uint => mapping (address => uint)) public gameAccountLoyaltyPoints;

  // Tracks the user's spending of Loyalty Points.
  mapping(uint => mapping (address => uint)) public gameAccountPointsSpent;

  // Used to manage updates to gameAccountStaked and gameStake;
  mapping(uint => mapping (address => uint)) public gameAccountStakeWeek;

  // Tracks the user's current stake
  mapping(uint => mapping (address => uint)) public gameAccountStaked;

  mapping(address => uint) public loyaltyPartners;

  // Tracks the current
  mapping(address => uint) public loyaltyWeeks;

  function getCurrentWeek()
    public
    view
  returns(uint) {
    return (block.timestamp - WEEK_ZERO_START) / SECONDS_PER_WEEK;
  }

  function workerGrantLoyaltyPoints(uint game_, address account_, uint pointsGrant_)
    external
    workerOrMinion
  {
    emit LoyaltyPointsGranted(game_, account_, pointsGrant_);
    _addLoyaltyPoints(game_, account_, pointsGrant_);
  }

  function _addLoyaltyPoints(uint game_, address account_, uint pointsGrant_)
    internal
  {
    gameAccountLoyaltyPoints[game_][account_] = gameAccountLoyaltyPoints[game_][account_].add(pointsGrant_);

    uint newBalance = getLoyaltyPointsGranted(game_, account_);

    emit LoyaltyPointsChange(
      game_,
      account_,
      getCurrentWeek(),
      gameAccountStaked[game_][account_],
      newBalance,
      gameAccountPointsSpent[game_][account_]);
  }

  function workerRemoveLoyaltyPoints(uint game_, address account_, uint pointsToRemove_)
    external
    workerOrMinion
  {
    gameAccountLoyaltyPoints[game_][account_] = gameAccountLoyaltyPoints[game_][account_].sub(pointsToRemove_);

    uint newBalance = getLoyaltyPointsGranted(game_, account_);

    emit LoyaltyPointsRemoved(game_, account_, pointsToRemove_);
    emit LoyaltyPointsChange(
      game_,
      account_,
      getCurrentWeek(),
      gameAccountStaked[game_][account_],
      newBalance,
      gameAccountPointsSpent[game_][account_]);
  }

  function approveThirdPartyLoyaltySpender(address contract_, bool isSpender_)
    external
    onlyCFO
  {
    if(isSpender_) {
      require(!approvedLoyaltySpenders[contract_], "Contract is already a spender");
    } else {
      require(approvedLoyaltySpenders[contract_], "Contract isn't an existing spender");
    }
    approvedLoyaltySpenders[contract_] = isSpender_;
    emit ThirdPartyRewwardsSpender(contract_, isSpender_);
  }

  function thirdPartySpendLoyaltyPoints(uint game_, address account_, uint pointsToSpend_)
    external
    override
  {
    // Cannot be called using native meta-transactions
    require(approvedLoyaltySpenders[msg.sender], "must be an approved Loyalty Points spender contract");
    _spendLoyaltyPoints(game_, account_, pointsToSpend_);
  }

  function workerSpendLoyaltyPoints(uint game_, address account_, uint pointsToSpend_)
    external
    workerOrMinion
  {
    _spendLoyaltyPoints(game_, account_, pointsToSpend_);
  }

  function _spendLoyaltyPoints(uint game_, address account_, uint pointsToSpend_)
    internal
  {
    uint currentPoints = getLoyaltyPointsGranted(game_, account_);
    // Ensure balance is sufficient
    uint newSpend = gameAccountPointsSpent[game_][account_].add(pointsToSpend_);
    require(currentPoints >= newSpend, "spent more Loyalty Points than current balance");
    gameAccountPointsSpent[game_][account_] = newSpend;
    emit LoyaltyPointsChange(game_, account_, getCurrentWeek(), gameAccountStaked[game_][account_], currentPoints, newSpend);
  }

  // What happens if we spend during an update; we don't want to update the actual balance, just calculate it.
  function getLoyaltyPointsGranted(uint game_, address account_)
    public
    override
    view
  returns(uint currentPoints)
  {
    uint stakeWeek = gameAccountStakeWeek[game_][account_];
    uint _currentWeek = getCurrentWeek();
    uint currentStake = gameAccountStaked[game_][account_];


    currentPoints = gameAccountLoyaltyPoints[game_][account_]
      .add((_currentWeek.sub(stakeWeek)).mul(currentStake.div(gcPerLoyaltyPoint)));
    // add their outstanding balance LP 

    uint currentPartner = loyaltyPartners[account_]; 
    if(currentPartner == game_ && game_ != 0) {
      uint loyaltyWeek = loyaltyWeeks[account_];
      if(loyaltyWeek < _currentWeek) {
        uint balance = _balances[account_];
        uint pointsToAdd = balance.div(gcPerLoyaltyPoint).mul(_currentWeek.sub(loyaltyWeek));
        currentPoints = currentPoints.add(pointsToAdd);
      }
    }
  }

  function getLoyaltyPointSpends(uint game_, address account_)
    public
    override
    view
  returns(uint totalSpend)
  {
    totalSpend = gameAccountPointsSpent[game_][account_];
  }

  function getLoyaltyPointsTotal(uint game_, address account_)
    public
    override
    view
  returns(uint totalRemaining)
  {
    uint points = getLoyaltyPointsGranted(game_, account_);
    uint spent = getLoyaltyPointSpends(game_, account_);
    if(points <= spent) {
      totalRemaining = 0;
    } else {
      totalRemaining = points.sub(spent);
    }
  }

  // Internal transfer of ERC20 tokens to complete payment of an auction.
  // @param from_ The address which you want to send tokens from
  // @param to_ The address which you want to transfer to
  // @param value_ The amout of tokens to be transferred
  function _beforeTokenTransfer(address from_, address to_, uint256 value_)
    internal
    override
  {
    if(from_ != address(0)) {
      emit Balance(from_, _balances[from_].sub(value_));
      _updateLoyalty(from_);
    }
    if(to_ != address(0)) {
      emit Balance(to_, _balances[to_].add(value_));
      _updateLoyalty(to_);
    }
  }

  function selectLoyaltyPartner(uint partnerId_)
    external
  {
    _setLoyaltyPartner(_msgSender(), partnerId_);
  }

  function workerSelectLoyaltyPartner(address account_, uint partnerId_)
    external
    workerOrMinion
  {
    _setLoyaltyPartner(account_, partnerId_);
  }


  // When a user picks a game,
  // if the user has a game picked and their last update week is last week or before
  // then grant N weeks of LP based on their prior balance
  // and update their last update week to this week
  function _setLoyaltyPartner(address account_, uint partnerId_)
    internal
  {
    _updateLoyalty(account_);
    uint currentPartner = loyaltyPartners[account_];
    loyaltyPartners[account_] = partnerId_;
    uint loyaltyWeek = loyaltyWeeks[account_];
    uint currentWeek = getCurrentWeek();
    if(loyaltyWeek == 0) {
      loyaltyWeeks[account_] = currentWeek;
    }
    if(currentPartner != partnerId_) {
      emit LoyaltyPartnerSet(partnerId_, account_, currentWeek);
    }
  }

  // handle loyalty points here
  // if the user has a game picked and their last update week is last week or before
  // then grant N weeks of LP based on their prior balance
  // and update their last update week to this week
  function _updateLoyalty(address account_)
    internal
  {
    uint currentPartner = loyaltyPartners[account_]; 
    if(currentPartner != 0) {
      uint loyaltyWeek = loyaltyWeeks[account_];
      uint currentWeek = getCurrentWeek();
      if(loyaltyWeek < currentWeek) {
        uint balance = _balances[account_];
        uint pointsToAdd = balance.div(gcPerLoyaltyPoint).mul(currentWeek.sub(loyaltyWeek));
        _addLoyaltyPoints(currentPartner, account_, pointsToAdd);
        loyaltyWeeks[account_] = currentWeek;
      }
    }
  }
}

// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract GAME_ERC20Staking is GAME_ERC20Loyalty {
  using SafeMath for uint256;

  event OracleTransaction(bytes32 indexed txHash);

  uint[] public gameStakeLevelCaps = [1, 2, 3, 4, 5, 6, 100000000000];

  uint public gameLevelPoints = 50;
  uint public auctionSitePoints = 100;
  uint public totalFeePoints = 400;


  // Tracks the current stake of each game.
  mapping(uint => uint) public gameStaked;
  // Stake
  uint public totalStaked;


  mapping(bytes32 => bool) public updateStakesOracleHashes;

  function setGameLevelPoints(uint points_)
    external
    onlyCFO
  {
    require(points_ <= 100, "must be less than or equal to 1%");
    gameLevelPoints = points_;
    totalFeePoints = auctionSitePoints.add(points_.mul(6));
  }

  function setAuctionSitePoints(uint points_)
    external
    onlyCFO
  {
    require(points_ <= 500, "must be less than or equal to 5%");
    auctionSitePoints = points_;
    totalFeePoints = points_.add(gameLevelPoints.mul(6));
  }

  function setGameStakeLevelCaps(uint[7] calldata caps_)
    external
    onlyCFO
  {
    uint previousData = 0;
    uint cap = 0;
    for(uint i = 0; i < 7; i++) {
      cap = caps_[i];
      require(cap > previousData, "caps must be ascending and non-zero");
      gameStakeLevelCaps[i] = cap;
      previousData = cap;
    }
    require(cap == 100000000000, "highest cap must be 100 billion");
  }

  function getGameStakeLevel(uint game_)
    public
    view
  returns (uint level) {
    uint gameStake = gameStaked[game_];
    for(level = 0; level < 7; level++) {
      if(gameStake < gameStakeLevelCaps[level]) {
        return level;
      }
    }
  }

  function getGameBalance(uint game_)
    public
    override
    view
  returns(uint balance) {
    balance = _balances[game_ == 0 ? address(this) : address(game_)];
  }

  // @dev Internal function to calculate the game, account, and total stakes on a stake change
  // @param week_ - the week we're updating (must be current or past)
  // @param game_ - the game to be staked on
  // @param staker_ - the account doing the staking
  // @param newStake_ - the newly updated stake of the staker on that game
  function oracleUpdateStakes(bytes32 txHash_, uint week_, uint game_, address staker_, uint newStake_)
    external
    workerOrMinion
  {
    if(updateStakesOracleHashes[txHash_]) {
      return;
    }
    updateStakesOracleHashes[txHash_] = true;
    emit OracleTransaction(txHash_);

    uint _currentWeek = getCurrentWeek();
    require(week_ <= _currentWeek, "requested week must be now or in the past");
    require(newStake_ <= 10 ** 29, "account stake underflow - must be <100Bn");

    // Check if the week is (a) less (do nothing), (b) equal (diff the stake), (c) greater (update everything)
    uint stakeWeek = gameAccountStakeWeek[game_][staker_];

    // If this is data for a previous week, ignore it
    // (we could adjust based on complex logic, but ignore is safer)
    require(stakeWeek <= week_, "requested week must be equal or later than stake week");

    uint playerStake = gameAccountStaked[game_][staker_];
    bool isStakeIncrease = newStake_ > playerStake ? true : false;
    uint stakeChange = isStakeIncrease ? newStake_ - playerStake : playerStake - newStake_;
    // update gameAccountStaked to the new stake amount
    // update gameStake based on the diff
    // update totalStake based on the diff
    gameAccountStakeWeek[game_][staker_] = week_;
    gameAccountStaked[game_][staker_] = newStake_;
    gameStaked[game_] = isStakeIncrease
      ? gameStaked[game_] + stakeChange
      : gameStaked[game_] - stakeChange;
    require(gameStaked[game_] <= 10 ** 29, "game stake underflow");
    totalStaked = isStakeIncrease
      ? totalStaked + stakeChange
      : totalStaked - stakeChange;
    require(totalStaked <= 10 ** 29, "total stake underflow");

    uint weeksToPay = (stakeWeek >= _currentWeek || stakeWeek >= week_ || stakeWeek == 0)
      ? 0
      : week_ - stakeWeek;
    uint pointsSpent = gameAccountPointsSpent[game_][staker_];
    // Update the Loyalty Points with the change
    gameAccountLoyaltyPoints[game_][staker_] = gameAccountLoyaltyPoints[game_][staker_].add(weeksToPay.mul(playerStake.div(gcPerLoyaltyPoint)));
    // If the last edit was made more than a week ago, collect Loyalty Points for the intervening weeks.

    // The current points is "what the points would be if you
    uint grantedPoints = getLoyaltyPointsGranted(game_, staker_);

    emit LoyaltyPointsChange(
      game_,
      staker_,
      week_,
      newStake_,
      grantedPoints,
      pointsSpent);
  }
}


// @title Auction Base
// @dev Contains models, variables, and internal methods for the auction.
// @notice We omit a fallback function to prevent accidental sends to this contract.
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract AuctionBase is GAME_ERC20Staking {
  using SafeMath for uint256;

  // @dev Map from tokenId to their corresponding auction data.
  // @notice We use two uints here because it's much more efficient than a struct
  mapping (uint => uint) public auctionIdToMetadata;
  mapping (uint => uint) public auctionIdToPrices;

  event AuctionCreated(
    address indexed seller,
    uint indexed tokenId,
    uint startingPrice,
    uint endingPrice,
    uint startTime,
    uint duration
  );

  event AuctionSuccessful(
    address indexed seller,
    address indexed buyer,
    uint indexed tokenId,
    uint totalPrice
  );

  event AuctionCancelled(address indexed seller, uint indexed tokenId);

  // @dev Adds an auction to the list of open auctions. Also fires the
  //  AuctionCreated event.
  // @param tokenId_ The Id of the token to be put on auction.
  // @param startingPrice - the start price of the Auction to add.
  // @param endingPrice - the end price of the Auction to add.
  // @param duration - the length of the Auction in seconds.
  // @param seller - the seller of the token.
  function _addAuction(
    uint tokenId_,
    uint startingPrice_,
    uint endingPrice_,
    uint duration_,
    address seller_
  )
    internal
  {
    require(duration_ == uint(uint48(duration_)), "add auction: duration must be a uint48");
    require(startingPrice_ == uint(uint128(startingPrice_)), "add auction: start price must be a uint128");
    require(endingPrice_ == uint(uint128(endingPrice_)), "add auction: end price must be a uint128");
    require(startingPrice_ > 0, "starting price must be non-zero");
    require(endingPrice_ > 0, "ending price must be non-zero");
    // Require that all auctions have a duration of
    // at least one minute. (Keeps our math from getting hairy!)
    require(duration_ >= 1 minutes, "auctions must be 1 minute long or more");

    uint auctionMetadata = uint(seller_)|duration_<<160|uint(uint48(block.timestamp))<<208;
    uint auctionPrices = endingPrice_|startingPrice_<<128;
    auctionIdToMetadata[tokenId_] = auctionMetadata;
    auctionIdToPrices[tokenId_] = auctionPrices;

    emit AuctionCreated(
      seller_,
      uint(tokenId_),
      uint(startingPrice_),
      uint(endingPrice_),
      uint(block.timestamp),
      uint(duration_)
    );
  }

  // @dev Cancels an auction unconditionally.
  // @param tokenId_ The Id of the token to cancelled.
  // @param seller_ - the seller of the token.
  function _cancelAuction(uint tokenId_, address seller_)
    internal
  {
    _removeAuction(tokenId_);
    erc721Contract.auctionTransfer(address(this), seller_, tokenId_);
    emit AuctionCancelled(seller_, tokenId_);
  }

  // @dev Retrieves the auction details for the requested auction
  // @param tokenId_ The Id of the token to be bid on.
  function _getAuction(uint tokenId_)
    internal
    view
    returns
  (
    address seller,
    uint startingPrice,
    uint endingPrice,
    uint duration,
    uint startedAt
  )
  {
    uint auctionMetadata = auctionIdToMetadata[tokenId_];
    uint auctionPrices = auctionIdToPrices[tokenId_];
    seller = address(auctionMetadata);
    duration = uint(uint48(auctionMetadata>>160));
    startedAt = uint(uint48(auctionMetadata>>208));
    startingPrice = uint(uint128(auctionPrices>>128));
    endingPrice = uint(uint128(auctionPrices));
  }

  // @dev Removes an auction from the list of open auctions.
  // @param tokenId_ - Id of NFT on auction.
  function _removeAuction(uint tokenId_)
    internal
  {
    delete auctionIdToMetadata[tokenId_];
    delete auctionIdToPrices[tokenId_];
  }

  // @dev Returns true if the NFT is on auction.
  // @param startedAt - the start time of the Auction to check.
  function _isOnAuction(uint startedAt_)
    internal
    pure
  returns (bool) {
    return (startedAt_ > 0);
  }

  // @dev Returns current price of an NFT on auction. Broken into two
  //  functions (this one, that computes the duration from the auction
  //  structure, and the other that does the price computation) so we
  //  can easily test that the price computation works correctly.
  function _auctionCurrentPrice(uint startingPrice_, uint endingPrice_, uint duration_, uint startedAt_)
    internal
    view
    returns (uint)
  {
    require(_isOnAuction(startedAt_), "must be on auction");
    uint secondsPassed = 0;

    // A bit of insurance against negative values (or wraparound).
    // Probably not necessary (since Ethereum guarnatees that the
    // now variable doesn't ever go backwards).
    if (block.timestamp > startedAt_) {
      secondsPassed = block.timestamp.sub(startedAt_);
    }

    return _computeAuctionCurrentPrice(
      startingPrice_,
      endingPrice_,
      duration_,
      secondsPassed
    );
  }

  // @dev Computes the current price of an auction. Factored out
  //  from _currentPrice so we can run extensive unit tests.
  //  When testing, make this function public and turn on
  //  `Current price computation` test suite.
  function _computeAuctionCurrentPrice(
    uint startingPrice_,
    uint endingPrice_,
    uint duration_,
    uint secondsPassed_
  )
    internal
    pure
    returns (uint)
  {
    // NOTE: We don't use SafeMath (or similar) in this function because
    //  all of our public functions cap the maximum values for
    //  time (at 48-bits) and currency (at 128-bits). duration_ is
    //  also known to be non-zero (see the require() statement in
    //  _addAuction())
    if (secondsPassed_ >= duration_) {
      // We've reached the end of the dynamic pricing portion
      // of the auction, just return the end price.
      return endingPrice_;
    } else {
      // Starting price can be higher than ending price (and often is!), so
      // this delta can be negative.
      int256 totalPriceChange = int256(endingPrice_) - int256(startingPrice_);

      // This multiplication can't overflow, secondsPassed_ will easily fit within
      // 48-bits, and totalPriceChange will easily fit within 128-bits, their product
      // will always fit within 256-bits.
      int256 currentPriceChange = totalPriceChange * int256(secondsPassed_) / int256(duration_);

      // currentPriceChange can be negative, but if so, will have a magnitude
      // less that startingPrice_. Thus, this result will always end up positive.
      int256 currentPrice = int256(startingPrice_) + currentPriceChange;

      return uint(currentPrice);
    }
  }

  function _payForAuction(uint game_, uint price_, address auctionSite_, address seller_, address buyer_)
    internal
  {
    uint totalFee = price_.mul(totalFeePoints).div(10000);
    uint level = getGameStakeLevel(game_);
    uint auctioneerFee = auctionSite_ == address(0) ? 0 : price_.mul(auctionSitePoints).div(10000);
    uint gameFee = price_.mul(level).mul(gameLevelPoints).div(10000);
    uint systemFee = totalFee.sub(auctioneerFee).sub(gameFee);

    // Transfer payment to the seller, then from the seller to the fee takers.
    _transfer(buyer_, seller_, price_);
    _transfer(seller_, address(this), systemFee);
    _transfer(seller_, game_ == 0 ? address(this) : address(game_), gameFee);
    if(auctioneerFee > 0) {
      _transfer(seller_, auctionSite_, auctioneerFee);
    }
  }
}



// @title ERC-721 Non-Fungible Token Standard
// @dev Interface for contracts conforming to ERC-721: Non-Fungible Tokens
// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
//  Note: the ERC-165 identifier for this interface is 0x80ac58cd

interface iERC721 {

  // @notice Count all NFTs assigned to an owner
  // @dev NFTs assigned to the zero address are considered invalid, and this
  //  function throws for queries about the zero address.
  // @param owner_ An address for whom to query the balance
  // @return The number of NFTs owned by `owner_`, possibly zero
  function balanceOf(address owner_) external view returns (uint);

  // @notice Find the owner of an NFT
  // @param tokenId_ The identifier for an NFT
  // @dev NFTs assigned to zero address are considered invalid, and queries
  //  about them do throw.
  // @return The address of the owner of the NFT
  function ownerOf(uint tokenId_) external view returns (address);

  // @notice Transfers the ownership of an NFT from one address to another address
  // @dev Throws unless `msg.sender` is the current owner, an authorized
  //  operator, or the approved address for this NFT. Throws if `from_` is
  //  not the current owner. Throws if `to_` is the zero address. Throws if
  //  `tokenId_` is not a valid NFT. When transfer is complete, this function
  //  checks if `to_` is a smart contract (code size > 0). If so, it calls
  //  `onERC721Received` on `to_` and throws if the return value is not
  //  `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`.
  // @param from_ The current owner of the NFT
  // @param to_ The new owner
  // @param tokenId_ The NFT to transfer
  // @param data Additional data with no specified format, sent in call to `to_`
  function safeTransferFrom(address from_, address to_, uint tokenId_, bytes calldata data_) external;

  // @notice Transfers the ownership of an NFT from one address to another address
  // @dev This works identically to the other function with an extra data parameter,
  //  except this function just sets data to ""
  // @param from_ The current owner of the NFT
  // @param to_ The new owner
  // @param tokenId_ The NFT to transfer
  function safeTransferFrom(address from_, address to_, uint tokenId_) external;

  // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
  //  TO CONFIRM THAT `to_` IS CAPABLE OF RECEIVING NFTS OR ELSE
  //  THEY MAY BE PERMANENTLY LOST
  // @dev Throws unless `msg.sender` is the current owner, an authorized
  //  operator, or the approved address for this NFT. Throws if `from_` is
  //  not the current owner. Throws if `to_` is the zero address. Throws if
  //  `tokenId_` is not a valid NFT.
  // @param from_ The current owner of the NFT
  // @param to_ The new owner
  // @param tokenId_ The NFT to transfer
  function transferFrom(address from_, address to_, uint tokenId_) external;

  // @notice Set or reaffirm the approved address for an NFT
  // @dev The zero address indicates there is no approved address.
  // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
  //  operator of the current owner.
  // @param approved_ The new approved NFT controller
  // @param tokenId_ The NFT to approve
  function approve(address approved_, uint tokenId_) external;

  // @notice Enable or disable approval for a third party ("operator") to manage
  //  all your assets.
  // @dev Throws unless `msg.sender` is the current NFT owner.
  // @dev Emits the ApprovalForAll event
  // @param operator_ Address to add to the set of authorized operators.
  // @param approved_ True if the operators is approved, false to revoke approval
  function setApprovalForAll(address operator_, bool approved_) external;

  // @notice Get the approved address for a single NFT
  // @dev Throws if `tokenId_` is not a valid NFT
  // @param tokenId_ The NFT to find the approved address for
  // @return The approved address for this NFT, or the zero address if there is none
  function getApproved(uint tokenId_) external view returns (address);

  // @notice Query if an address is an authorized operator for another address
  // @param owner_ The address that owns the NFTs
  // @param operator_ The address that acts on behalf of the owner
  // @return True if `operator_` is an approved operator for `owner_`, false otherwise
  function isApprovedForAll(address owner_, address operator_) external view returns (bool);
}


// @title AuctionContract
// @dev Clock auction designed for sale of tokens
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

abstract contract AuctionExternal is AuctionBase {

  // @dev Returns auction info for an NFT on auction.
  // @param tokenId_ - Id of NFT on auction.
  function getExistingAuction(uint tokenId_)
    external
    view
    returns
  (
    address seller,
    uint startingPrice,
    uint endingPrice,
    uint duration,
    uint startedAt
  )
  {
    (seller, startingPrice, endingPrice, duration, startedAt) = _getAuction(tokenId_);

    require(_isOnAuction(startedAt), "must be on auction");
  }

  // @dev Returns the current price of an auction.
  // @param tokenId_ - Id of the token price we are checking.
  function getAuctionCurrentPrice(uint tokenId_)
    external
    view
  returns (uint) {
    address seller;
    uint startingPrice;
    uint endingPrice;
    uint duration;
    uint startedAt;
    (seller, startingPrice, endingPrice, duration, startedAt) = _getAuction(tokenId_);
    return _auctionCurrentPrice(startingPrice, endingPrice, duration, startedAt);
  }

  // @dev Put a token up for auction. Does some ownership trickery to create auctions in one tx.
  //   Also fires the AuctionCreated event.
  // @param tokenId_ The Id of the token to be put on auction.
  // @param startingPrice_ - the start price of the Auction to add.
  // @param endingPrice_ - the end price of the Auction to add.
  // @param duration_ - the length of the Auction in seconds.
  function createAuction(
    uint tokenId_,
    uint startingPrice_,
    uint endingPrice_,
    uint duration_
  )
    external
  {
    // Sanity check that no inputs overflow how many bits we've allocated
    // to store them in the auction struct.
    require(startingPrice_ == uint(uint128(startingPrice_)), "starting price under/overflow");
    require(endingPrice_ == uint(uint128(endingPrice_)), "ending price under/overflow");
    require(duration_ == uint(uint48(duration_)), "duration under/overflow");

    // Our auctions are only Dutch or fixed price.
    require(startingPrice_ >= endingPrice_, "starting price must be >= ending price");

    // Auctions can be no more than 7 days, and no less than 10 minutes
    require(duration_ <= 7 days, "duration must be <= 7 days");
    require(duration_ >= 10 minutes, "duration must be >= 10 minutes");

    address sender = _msgSender();
    // This checks "can transfer"
    erc721Contract.auctionTransfer(sender, address(this), tokenId_);
    // Auction throws if inputs are invalid and clears transfer of the token.

    _addAuction(tokenId_, startingPrice_, endingPrice_, duration_, sender);
  }

  // @dev Bids on an open auction, completing the auction and transferring
  //  ownership of the NFT if enough Ether is supplied.
  // @param tokenId_ - Id of token to bid on.
  // @param bidAmount_ - The amount of the bid (for safety, to ensure people don't pay too much)
  // @param auctioneer_ - The account that will receive 1% of the auction proceeds
  //   Usually, an exchange website will put its own address in as auctioneer_, so it can
  //   earn revenue for the public-facing portion of sales.
  function bidOnAuction(uint tokenId_, uint bidAmount_, address auctioneer_)
    external
  {
    address seller;
    uint startingPrice;
    uint endingPrice;
    uint duration;
    uint startedAt;
    (seller, startingPrice, endingPrice, duration, startedAt) = _getAuction(tokenId_);

    // This contract must own the on sale token
    require(iERC721(address(erc721Contract)).ownerOf(tokenId_) == address(this), "contract must own on-sale token");

    // Explicitly check that this auction is currently live.
    require(_isOnAuction(startedAt), "auction must be live");

    // Check that the bid is greater than or equal to the current price
    uint price = _auctionCurrentPrice(startingPrice, endingPrice, duration, startedAt);
    require(bidAmount_ >= price, "bid must be greater than or equal to price");

    // The bid is good! Remove the auction before sending the fees
    // so we can't have a reentrancy attack.
    _removeAuction(tokenId_);

    uint game = uint256(uint64(tokenId_));
    address sender = _msgSender();

    // Transfer the payment from the buyer to the seller, and the fees to the game, system, and auctioneer
    _payForAuction(game, price, auctioneer_, seller, sender);

    // Tell the world!
    emit AuctionSuccessful(seller, sender, tokenId_, price);

    // Reassign ownership (also clears pending approvals and emits Transfer event).
    erc721Contract.auctionTransfer(address(this), sender, tokenId_);
  }

  // @dev Cancels an auction that hasn't been won yet.
  //  Returns the NFT to original owner.
  // @param tokenId_ - Id of token on auction
  function cancelAuction(uint tokenId_)
    external
  {
    uint auctionMetadata = auctionIdToMetadata[tokenId_];
    address seller = address(auctionMetadata);
    uint startedAt = uint(uint48(auctionMetadata>>208));

    require(_isOnAuction(startedAt), "token must be on auction");
    require(_msgSender() == seller, "token seller must be sender");
    _cancelAuction(tokenId_, seller);
  }

  // @dev Cancels an auction.
  //  Only the manager may do this, and NFTs are returned to
  //  the seller. This should only be used in emergencies.
  // @param tokenId_ - Id of the NFT on auction to cancel.
  function cancelAuctionByManager(uint tokenId_)
    external
    override
    onlyLocalContract
  {
    uint auctionMetadata = auctionIdToMetadata[tokenId_];
    address seller = address(auctionMetadata);
    uint startedAt = uint(uint48(auctionMetadata>>208));
    require(_isOnAuction(startedAt), "token must be on auction");
    _cancelAuction(tokenId_, seller);
  }
}


// @title GAME Credits ERC20 contract
// @dev ERC20 management contract, designed to make using ERC-20 tokens easier
// @author GAME Credits (gamecredits.org)
// (c) 2020 GAME Credits All Rights Reserved. This code is not open source.

contract GAME_ERC20 is AuctionExternal {
  using SafeMath for uint256;

  string constant public CONTRACT_ERC712_VERSION = "1";
  string constant public CONTRACT_ERC712_NAME = "GAME Credits Sidechain ERC20 Contract";

  // @dev Constructor creates a reference to the master contract
  //  and the ERC20 depositor contract.
  // @param masterContract_ - address of the master contract
  // @param depositor_ - address of the erc20 depositor contract
  // @param rootChainId_ - ID of the chain the contract is deployed on
  constructor(address masterContract_, address depositor_)
    GAME_ERC20Access(masterContract_)
    ChildERC20("GAME Credits", "GAME", 18, depositor_)
    NetworkAgnostic(CONTRACT_ERC712_NAME, CONTRACT_ERC712_VERSION)
  {
  }

  // @dev Withdraws the whole balance of a game to an admin account.
  // @param uint game_ The game Id of the game for which sender is an admin
  function withdrawGameBalance(uint game_)
    external
    onlyGameAdmin(game_)
  {
    require(game_ > 0, "can't withdraw from the zero address");
    _transfer(address(game_), _msgSender(), _balances[address(game_)]);
  }

  // @dev Withdraws the whole balance of the system to an admin account.
  // @param uint game_ The game Id of the game for which sender is an admin
  function withdrawSystemBalance()
    external
    onlyCFO
  {
    _transfer(address(this), _msgSender(), _balances[address(this)]);
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"masterContract_","type":"address"},{"internalType":"address","name":"depositor_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"AuctionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endingPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"AuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPrice","type":"uint256"}],"name":"AuctionSuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Balance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"game","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"week","type":"uint256"}],"name":"LoyaltyPartnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"game","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"week","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalGranted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSpent","type":"uint256"}],"name":"LoyaltyPointsChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"game","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"pointsGrant","type":"uint256"}],"name":"LoyaltyPointsGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"game","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"pointsRemoved","type":"uint256"}],"name":"LoyaltyPointsRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"OracleTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"spenderContract","type":"address"},{"indexed":false,"internalType":"bool","name":"isSpender","type":"bool"}],"name":"ThirdPartyRewwardsSpender","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CONTRACT_ERC712_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTRACT_ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK_ZERO_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bool","name":"isSpender_","type":"bool"}],"name":"approveThirdPartyLoyaltySpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedLoyaltySpenders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionIdToMetadata","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionIdToPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionSitePoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"bidAmount_","type":"uint256"},{"internalType":"address","name":"auctioneer_","type":"address"}],"name":"bidOnAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"cancelAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"cancelAuctionByManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"startingPrice_","type":"uint256"},{"internalType":"uint256","name":"endingPrice_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"}],"name":"createAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"encodeDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"encodeWorkerDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721Contract","outputs":[{"internalType":"contract iGAME_ERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"gameAccountLoyaltyPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"gameAccountPointsSpent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"gameAccountStakeWeek","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"gameAccountStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameContract","outputs":[{"internalType":"contract iGAME_Game","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameLevelPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"gameStakeLevelCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"gameStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gcPerLoyaltyPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getAuctionCurrentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getCurrentWeek","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getExistingAuction","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"startingPrice","type":"uint256"},{"internalType":"uint256","name":"endingPrice","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"startedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"}],"name":"getGameBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"}],"name":"getGameStakeLevel","outputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"}],"name":"getLoyaltyPointSpends","outputs":[{"internalType":"uint256","name":"totalSpend","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"}],"name":"getLoyaltyPointsGranted","outputs":[{"internalType":"uint256","name":"currentPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"}],"name":"getLoyaltyPointsTotal","outputs":[{"internalType":"uint256","name":"totalRemaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWorkerDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isLocalContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"gameContract_","type":"address"},{"internalType":"address","name":"erc721Contract_","type":"address"}],"name":"linkContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"localContracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"loyaltyPartners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"loyaltyWeeks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterContract","outputs":[{"internalType":"contract iGAME_Master","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash_","type":"bytes32"},{"internalType":"uint256","name":"week_","type":"uint256"},{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"staker_","type":"address"},{"internalType":"uint256","name":"newStake_","type":"uint256"}],"name":"oracleUpdateStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"partnerId_","type":"uint256"}],"name":"selectLoyaltyPartner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"points_","type":"uint256"}],"name":"setAuctionSitePoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor_","type":"address"}],"name":"setDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"points_","type":"uint256"}],"name":"setGameLevelPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[7]","name":"caps_","type":"uint256[7]"}],"name":"setGameStakeLevelCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"pointsToSpend_","type":"uint256"}],"name":"thirdPartySpendLoyaltyPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFeePoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transferByContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bool","name":"isLocal_","type":"bool"}],"name":"updateLocalContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"updateStakesOracleHashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"}],"name":"withdrawGameBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawSystemBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"},{"internalType":"bytes32","name":"replayPrevention_","type":"bytes32"},{"internalType":"bytes","name":"functionSignature_","type":"bytes"},{"internalType":"bytes32","name":"sigR_","type":"bytes32"},{"internalType":"bytes32","name":"sigS_","type":"bytes32"},{"internalType":"uint8","name":"sigV_","type":"uint8"}],"name":"workerExecuteMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"pointsGrant_","type":"uint256"}],"name":"workerGrantLoyaltyPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"pointsToRemove_","type":"uint256"}],"name":"workerRemoveLoyaltyPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"partnerId_","type":"uint256"}],"name":"workerSelectLoyaltyPartner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"game_","type":"uint256"},{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"pointsToSpend_","type":"uint256"}],"name":"workerSpendLoyaltyPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

670de0b6b3a764000060105561016060405260016080908152600260a052600360c052600460e05260056101005260066101205264174876e800610140526200004d9060179060076200035e565b5060326018556064601955610190601a553480156200006b57600080fd5b506040516200617738038062006177833981810160405260408110156200009157600080fd5b508051602091820151604080518082018252600c81526b47414d45204372656469747360a01b8186015281518083018352600481526347414d4560e01b818701528251606081019093526025808452949593948694929391926012928792909162006100908301396040805180820190915260018152603160f81b602082015285858383620001218282620001d1565b600055620001308282620002a9565b600155505081516200014a906005906020850190620003b7565b50805162000160906006906020840190620003b7565b50506007805460ff19166012179055506200017f915083905062000344565b600a80546001600160a01b039283166001600160a01b031991821617909155600b8054969092169516851790555050506000908152600e60205260409020805460ff1916600117905550620004419050565b600080620001de6200035a565b90508062000233576040805162461bcd60e51b815260206004820152601960248201527f636861696e204944206d757374206e6f74206265207a65726f00000000000000604482015290519081900360640190fd5b60405180608001604052806052815260200162006125605291398051602091820120855186830120855186840120604080518086019490945283810192909252606083015260808201939093523060a0808301919091528351808303909101815260c09091019092528151910120905092915050565b600080620002b66200035a565b90508060891480620002c85750806001145b620002e957806201388114620002e0576000620002e3565b60055b620002ec565b60015b60ff1690508062000233576040805162461bcd60e51b815260206004820152601960248201527f636861696e204944206d757374206e6f74206265207a65726f00000000000000604482015290519081900360640190fd5b6007805460ff191660ff92909216919091179055565b4690565b828054828255906000526020600020908101928215620003a5579160200282015b82811115620003a5578251829064ffffffffff169055916020019190600101906200037f565b50620003b39291506200042a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003fa57805160ff1916838001178555620003a5565b82800160010185558215620003a5579182015b82811115620003a55782518255916020019190600101906200040d565b5b80821115620003b357600081556001016200042b565b615caf80620004516000396000f3fe6080604052600436106104615760003560e01c80637672b33c1161023f578063b9c24a4811610139578063d7c97fb4116100b6578063f2c098b71161007a578063f2c098b714611507578063f40c96ab1461153a578063fbc394ea1461154f578063fbd2695b14611579578063fe6399b8146115b857610468565b8063d7c97fb41461144a578063dd62ed3e1461145f578063e1a1a66c1461149a578063e2340c95146114af578063e2b8e7d3146114c457610468565b8063cc165837116100fd578063cc1658371461136b578063cc9c6eeb14611380578063cd446e2214611395578063cf2c52cb146113aa578063d3f330091461143557610468565b8063b9c24a481461128f578063bdc3c59d146112b9578063be46fcb9146112ec578063c7977be714611325578063c7c4ff461461133a57610468565b8063a457c2d7116101c7578063ad2ded2b1161018b578063ad2ded2b14611118578063ad39f8b4146111df578063b26fcc5814611209578063b6acd1e614611233578063b74e32261461125c57610468565b8063a457c2d714611028578063a593d19114611061578063a84069631461108b578063a9059cbb146110b5578063ace31e7d146110ee57610468565b806396b5a7551161020e57806396b5a75514610f565780639a1d804414610f805780639dad1da514610fbf5780639f3fba5914610fe9578063a1fd47d61461101357610468565b80637672b33c14610ede578063817b1cd214610f1757806384ae2a7414610f2c57806395d89b4114610f4157610468565b80633250c6d11161035b5780635958b301116102d85780636d4b99e01161029c5780636d4b99e014610d185780636eb227ce14610e4e57806370a0823114610e6357806372012a0b14610e96578063765d6cce14610ec957610468565b80635958b30114610bcd5780635c57e2b314610c085780635f489a5314610c415780636138939a14610c80578063644b2b9f14610cdf57610468565b8063395093511161031f5780633950935114610acf5780633dc9abfa14610b085780633f990fc014610b4357806342bf989d14610b58578063431f21da14610b9157610468565b80633250c6d1146109e25780633408e47014610a0c57806335490cdd14610a2157806335e748fb14610a6c578063368a5a1a14610a9657610468565b806318160ddd116103e957806327430a42116103ad57806327430a421461080f5780632d0335ab146109455780632e1a7d4d146109785780632ed3aae3146109a2578063313ce567146109b757610468565b806318160ddd146107365780631b5eb0c11461074b5780631c9b5c0a1461078457806320379ee5146107b757806323b872dd146107cc57610468565b8063095ea7b311610430578063095ea7b3146105b157806309bcdcfe146105ea5780630c53c51c1461062657806312a92a56146106e8578063161e650d1461072157610468565b80630434f5fd1461046d57806304598bc2146104aa57806306fdde03146104e957806307c3353d1461057357610468565b3661046857005b600080fd5b34801561047957600080fd5b506104a86004803603604081101561049057600080fd5b506001600160a01b03813516906020013515156115f7565b005b3480156104b657600080fd5b506104a8600480360360608110156104cd57600080fd5b508035906001600160a01b0360208201351690604001356117e1565b3480156104f557600080fd5b506104fe6118f0565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610538578181015183820152602001610520565b50505050905090810190601f1680156105655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561057f57600080fd5b5061059d6004803603602081101561059657600080fd5b5035611987565b604080519115158252519081900360200190f35b3480156105bd57600080fd5b5061059d600480360360408110156105d457600080fd5b506001600160a01b03813516906020013561199c565b3480156105f657600080fd5b506106146004803603602081101561060d57600080fd5b50356119ba565b60408051918252519081900360200190f35b6104fe600480360360a081101561063c57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561066657600080fd5b82018360208201111561067857600080fd5b803590602001918460018302840111600160201b8311171561069957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020810135906040013560ff16611a0a565b3480156106f457600080fd5b506106146004803603604081101561070b57600080fd5b50803590602001356001600160a01b0316611d17565b34801561072d57600080fd5b50610614611d34565b34801561074257600080fd5b50610614611d3a565b34801561075757600080fd5b506106146004803603604081101561076e57600080fd5b50803590602001356001600160a01b0316611d40565b34801561079057600080fd5b5061059d600480360360208110156107a757600080fd5b50356001600160a01b0316611d5d565b3480156107c357600080fd5b50610614611d72565b3480156107d857600080fd5b5061059d600480360360608110156107ef57600080fd5b506001600160a01b03813581169160208101359091169060400135611d78565b34801561081b57600080fd5b506106146004803603604081101561083257600080fd5b810190602081018135600160201b81111561084c57600080fd5b82018360208201111561085e57600080fd5b803590602001918460018302840111600160201b8311171561087f57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156108d157600080fd5b8201836020820111156108e357600080fd5b803590602001918460018302840111600160201b8311171561090457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611dff945050505050565b34801561095157600080fd5b506106146004803603602081101561096857600080fd5b50356001600160a01b0316611f03565b34801561098457600080fd5b506104a86004803603602081101561099b57600080fd5b5035611f1e565b3480156109ae57600080fd5b50610614611f32565b3480156109c357600080fd5b506109cc611f3a565b6040805160ff9092168252519081900360200190f35b3480156109ee57600080fd5b506104a860048036036020811015610a0557600080fd5b5035611f43565b348015610a1857600080fd5b5061061461200b565b348015610a2d57600080fd5b506104a8600480360360a0811015610a4457600080fd5b508035906020810135906040810135906001600160a01b03606082013516906080013561200f565b348015610a7857600080fd5b5061061460048036036020811015610a8f57600080fd5b50356124dd565b348015610aa257600080fd5b5061061460048036036040811015610ab957600080fd5b50803590602001356001600160a01b03166124ef565b348015610adb57600080fd5b5061059d60048036036040811015610af257600080fd5b506001600160a01b038135169060200135612516565b348015610b1457600080fd5b506104a860048036036040811015610b2b57600080fd5b506001600160a01b0381358116916020013516612564565b348015610b4f57600080fd5b5061061461277c565b348015610b6457600080fd5b5061061460048036036040811015610b7b57600080fd5b50803590602001356001600160a01b0316612782565b348015610b9d57600080fd5b506104a860048036036080811015610bb457600080fd5b50803590602081013590604081013590606001356127c4565b348015610bd957600080fd5b506104a860048036036040811015610bf057600080fd5b506001600160a01b0381351690602001351515612a54565b348015610c1457600080fd5b506104a860048036036040811015610c2b57600080fd5b506001600160a01b038135169060200135612bee565b348015610c4d57600080fd5b506104a860048036036060811015610c6457600080fd5b508035906001600160a01b036020820135169060400135612cbb565b348015610c8c57600080fd5b50610caa60048036036020811015610ca357600080fd5b5035612ea3565b604080516001600160a01b03909616865260208601949094528484019290925260608401526080830152519081900360a00190f35b348015610ceb57600080fd5b5061061460048036036040811015610d0257600080fd5b50803590602001356001600160a01b0316612f18565b348015610d2457600080fd5b5061061460048036036040811015610d3b57600080fd5b810190602081018135600160201b811115610d5557600080fd5b820183602082011115610d6757600080fd5b803590602001918460018302840111600160201b83111715610d8857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610dda57600080fd5b820183602082011115610dec57600080fd5b803590602001918460018302840111600160201b83111715610e0d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612f35945050505050565b348015610e5a57600080fd5b50610614612f90565b348015610e6f57600080fd5b5061061460048036036020811015610e8657600080fd5b50356001600160a01b0316612fa0565b348015610ea257600080fd5b5061059d60048036036020811015610eb957600080fd5b50356001600160a01b0316612fbb565b348015610ed557600080fd5b5061059d612fd0565b348015610eea57600080fd5b5061061460048036036040811015610f0157600080fd5b50803590602001356001600160a01b0316612fd5565b348015610f2357600080fd5b50610614612ff2565b348015610f3857600080fd5b50610614612ff8565b348015610f4d57600080fd5b506104fe612fff565b348015610f6257600080fd5b506104a860048036036020811015610f7957600080fd5b5035613060565b348015610f8c57600080fd5b506104a860048036036060811015610fa357600080fd5b508035906001600160a01b036020820135169060400135613137565b348015610fcb57600080fd5b5061061460048036036020811015610fe257600080fd5b5035613190565b348015610ff557600080fd5b506104a86004803603602081101561100c57600080fd5b50356131c3565b34801561101f57600080fd5b506104a8613309565b34801561103457600080fd5b5061059d6004803603604081101561104b57600080fd5b506001600160a01b0381351690602001356133f8565b34801561106d57600080fd5b506106146004803603602081101561108457600080fd5b5035613460565b34801561109757600080fd5b506104a8600480360360208110156110ae57600080fd5b5035613495565b3480156110c157600080fd5b5061059d600480360360408110156110d857600080fd5b506001600160a01b0381351690602001356135d9565b3480156110fa57600080fd5b506106146004803603602081101561111157600080fd5b50356135ed565b6104fe600480360360c081101561112e57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561115d57600080fd5b82018360208201111561116f57600080fd5b803590602001918460018302840111600160201b8311171561119057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020810135906040013560ff166135ff565b3480156111eb57600080fd5b506106146004803603602081101561120257600080fd5b5035613990565b34801561121557600080fd5b506106146004803603602081101561122c57600080fd5b50356139a2565b34801561123f57600080fd5b506104a8600480360360e081101561125657600080fd5b506139c0565b34801561126857600080fd5b506106146004803603602081101561127f57600080fd5b50356001600160a01b0316613b6d565b34801561129b57600080fd5b506104a8600480360360208110156112b257600080fd5b5035613b7f565b3480156112c557600080fd5b50610614600480360360208110156112dc57600080fd5b50356001600160a01b0316613b90565b3480156112f857600080fd5b506106146004803603604081101561130f57600080fd5b50803590602001356001600160a01b0316613ba2565b34801561133157600080fd5b50610614613ce6565b34801561134657600080fd5b5061134f613d09565b604080516001600160a01b039092168252519081900360200190f35b34801561137757600080fd5b50610614613d18565b34801561138c57600080fd5b50610614613d1e565b3480156113a157600080fd5b5061134f613d24565b3480156113b657600080fd5b506104a8600480360360408110156113cd57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156113f757600080fd5b82018360208201111561140957600080fd5b803590602001918460018302840111600160201b8311171561142a57600080fd5b509092509050613d33565b34801561144157600080fd5b5061134f613dac565b34801561145657600080fd5b5061134f613dbb565b34801561146b57600080fd5b506106146004803603604081101561148257600080fd5b506001600160a01b0381358116916020013516613dca565b3480156114a657600080fd5b506104fe613df5565b3480156114bb57600080fd5b50610614613e11565b3480156114d057600080fd5b506104a8600480360360608110156114e757600080fd5b506001600160a01b03813581169160208101359091169060400135613e17565b34801561151357600080fd5b506104a86004803603602081101561152a57600080fd5b50356001600160a01b0316613e70565b34801561154657600080fd5b506104fe613f4c565b34801561155b57600080fd5b506104a86004803603602081101561157257600080fd5b5035613f69565b34801561158557600080fd5b506104a86004803603606081101561159c57600080fd5b508035906001600160a01b0360208201351690604001356140aa565b3480156115c457600080fd5b506104a8600480360360608110156115db57600080fd5b50803590602081013590604001356001600160a01b0316614169565b600b546001600160a01b031663b4ff232e611610614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561164d57600080fd5b505afa158015611661573d6000803e3d6000fd5b505050506040513d602081101561167757600080fd5b50516116c3576040805162461bcd60e51b815260206004820152601660248201527573656e646572206d757374206265207468652063666f60501b604482015290519081900360640190fd5b801561173c576001600160a01b0382166000908152600f602052604090205460ff1615611737576040805162461bcd60e51b815260206004820152601d60248201527f436f6e747261637420697320616c72656164792061207370656e646572000000604482015290519081900360640190fd5b611793565b6001600160a01b0382166000908152600f602052604090205460ff166117935760405162461bcd60e51b8152600401808060200182810382526022815260200180615c0b6022913960400191505060405180910390fd5b6001600160a01b0382166000818152600f6020908152604091829020805460ff191685151590811790915582519081529151600080516020615b168339815191529281900390910190a25050565b600b546001600160a01b03166317937a076117fa614411565b6040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b15801561183957600080fd5b505af115801561184d573d6000803e3d6000fd5b505050506040513d602081101561186357600080fd5b50516118a05760405162461bcd60e51b8152600401808060200182810382526024815260200180615a656024913960400191505060405180910390fd5b6040805182815290516001600160a01b0384169185917fd41290e38d33620ad1b04f29dd43f8c059267cc4fc1f8ed57a0f3d768efb5f919181900360200190a36118eb83838361446e565b505050565b60058054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561197c5780601f106119515761010080835404028352916020019161197c565b820191906000526020600020905b81548152906001019060200180831161195f57829003601f168201915b505050505090505b90565b601d6020526000908152604090205460ff1681565b60006119b06119a9614411565b84846144d5565b5060015b92915050565b6000818152601b60205260408120545b6007821015611a0357601782815481106119e057fe5b90600052602060002001548110156119f85750611a05565b6001909101906119ca565b505b919050565b6060611a14615692565b50604080516060810182526001600160a01b03881660008181526008602090815290849020548352820152908101869052611a5287828787876145c1565b611a8d5760405162461bcd60e51b8152600401808060200182810382526021815260200180615a896021913960400191505060405180910390fd5b6001600160a01b038716600090815260086020526040902054611ab1906001614669565b60086000896001600160a01b03166001600160a01b03168152602001908152602001600020819055507f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b87338860405180846001600160a01b03168152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611b59578181015183820152602001611b41565b50505050905090810190601f168015611b865780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a160006060306001600160a01b0316888a6040516020018083805190602001908083835b60208310611bd75780518252601f199092019160209182019101611bb8565b6001836020036101000a038019825116818451168082178552505050505050905001826001600160a01b031660601b8152601401925050506040516020818303038152906040526040518082805190602001908083835b60208310611c4d5780518252601f199092019160209182019101611c2e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611caf576040519150601f19603f3d011682016040523d82523d6000602084013e611cb4565b606091505b509150915081611d0b576040805162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c00000000604482015290519081900360640190fd5b98975050505050505050565b601260209081526000928352604080842090915290825290205481565b60015490565b60045490565b601360209081526000928352604080842090915290825290205481565b600f6020526000908152604090205460ff1681565b60005490565b6000611d858484846146ca565b611df584611d91614411565b611df085604051806060016040528060288152602001615a3d602891396001600160a01b038a16600090815260036020526040812090611dcf614411565b6001600160a01b031681526020810191909152604001600020549190614827565b6144d5565b5060019392505050565b600080611e0a61200b565b90508060891480611e1b5750806001145b611e3857806201388114611e30576000611e33565b60055b611e3b565b60015b60ff16905080611e8e576040805162461bcd60e51b8152602060048201526019602482015278636861696e204944206d757374206e6f74206265207a65726f60381b604482015290519081900360640190fd5b604051806080016040528060528152602001615976605291398051602091820120855186830120855186840120604080518086019490945283810192909252606083015260808201939093523060a0808301919091528351808303909101815260c09091019092528151910120905092915050565b6001600160a01b031660009081526008602052604090205490565b611f2f611f29614411565b826148be565b50565b635bb1638081565b60075460ff1690565b336000908152600e602052604090205460ff16611f915760405162461bcd60e51b8152600401808060200182810382526022815260200180615b366022913960400191505060405180910390fd5b6000818152601e60205260409020548060d081901c611faf816149ba565b611ffb576040805162461bcd60e51b81526020600482015260186024820152773a37b5b2b71036bab9ba1031329037b71030bab1ba34b7b760411b604482015290519081900360640190fd5b61200584836149bf565b50505050565b4690565b600b546001600160a01b03166317937a07612028614411565b6040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b15801561206757600080fd5b505af115801561207b573d6000803e3d6000fd5b505050506040513d602081101561209157600080fd5b50516120ce5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a656024913960400191505060405180910390fd5b6000858152601d602052604090205460ff16156120ea576124d6565b6000858152601d6020526040808220805460ff191660011790555186917f5b6a3ef0e5bffde11ba16a6f95c28598fd3c36913011167e2239d3ebcbc07f8591a26000612134612f90565b9050808511156121755760405162461bcd60e51b81526004018080602001828103825260298152602001806158f46029913960400191505060405180910390fd5b6c01431e0fae6d7217caa00000008211156121c15760405162461bcd60e51b8152600401808060200182810382526028815260200180615c2d6028913960400191505060405180910390fd5b60008481526013602090815260408083206001600160a01b0387168452909152902054858111156122235760405162461bcd60e51b81526004018080602001828103825260358152602001806159416035913960400191505060405180910390fd5b60008581526014602090815260408083206001600160a01b038816845290915281205490818511612255576000612258565b60015b90506000816122695785830361226d565b8286035b60008981526013602090815260408083206001600160a01b038c168085529083528184208e90558c84526014835281842090845290915290208790559050816122c7576000888152601b60205260409020548190036122d9565b6000888152601b602052604090205481015b6000898152601b602052604090208190556c01431e0fae6d7217caa00000001015612342576040805162461bcd60e51b815260206004820152601460248201527367616d65207374616b6520756e646572666c6f7760601b604482015290519081900360640190fd5b816123515780601c5403612357565b80601c54015b601c8190556c01431e0fae6d7217caa000000010156123b5576040805162461bcd60e51b8152602060048201526015602482015274746f74616c207374616b6520756e646572666c6f7760581b604482015290519081900360640190fd5b600085851015806123c65750898510155b806123cf575084155b6123db57848a036123de565b60005b60008a81526012602090815260408083206001600160a01b038d1684529091529020546010549192509061244b906124229061241b908890614a75565b8490614ab7565b60008c81526011602090815260408083206001600160a01b038f16845290915290205490614669565b60008b81526011602090815260408083206001600160a01b038e16845290915281209190915561247b8b8b613ba2565b604080518b81526020810183905280820185905290519192508d916001600160a01b038d16918e917f19f1796adcb2405f90c02fdd22577ab1e1bde3ba7966ccea9d3a3ea1f589287b9181900360600190a450505050505050505b5050505050565b601b6020526000908152604090205481565b60009182526012602090815260408084206001600160a01b03909316845291905290205490565b60006119b0612523614411565b84611df08560036000612534614411565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490614669565b336000908152600e602052604090205460ff166125b25760405162461bcd60e51b8152600401808060200182810382526022815260200180615b366022913960400191505060405180910390fd5b600c546001600160a01b031615612610576040805162461bcd60e51b815260206004820152601c60248201527f746f6b656e20636f6e7472616374206d75737420626520626c616e6b00000000604482015290519081900360640190fd5b600d546001600160a01b03161561266e576040805162461bcd60e51b815260206004820152601c60248201527f746f6b656e20636f6e7472616374206d75737420626520626c616e6b00000000604482015290519081900360640190fd5b600c80546001600160a01b038085166001600160a01b03199283168117909355600d8054918516919092161790556000818152600f6020908152604091829020805460ff1916600190811790915582519081529151600080516020615b168339815191529281900390910190a26001600160a01b0381166000818152600f6020908152604091829020805460ff1916600190811790915582519081529151600080516020615b168339815191529281900390910190a2600b80546001600160a01b039081166000908152600f6020908152604091829020805460ff191660019081179091559354825194855291519190921692600080516020615b1683398151915292908290030190a25050565b60195481565b60008061278f8484613ba2565b9050600061279d85856124ef565b90508082116127af57600092506127bc565b6127b98282614b10565b92505b505092915050565b826001600160801b03168314612821576040805162461bcd60e51b815260206004820152601d60248201527f7374617274696e6720707269636520756e6465722f6f766572666c6f77000000604482015290519081900360640190fd5b816001600160801b0316821461287e576040805162461bcd60e51b815260206004820152601b60248201527f656e64696e6720707269636520756e6465722f6f766572666c6f770000000000604482015290519081900360640190fd5b8065ffffffffffff1681146128da576040805162461bcd60e51b815260206004820152601760248201527f6475726174696f6e20756e6465722f6f766572666c6f77000000000000000000604482015290519081900360640190fd5b818310156129195760405162461bcd60e51b815260040180806020018281038252602681526020018061587c6026913960400191505060405180910390fd5b62093a80811115612971576040805162461bcd60e51b815260206004820152601a60248201527f6475726174696f6e206d757374206265203c3d20372064617973000000000000604482015290519081900360640190fd5b6102588110156129c8576040805162461bcd60e51b815260206004820152601e60248201527f6475726174696f6e206d757374206265203e3d203130206d696e757465730000604482015290519081900360640190fd5b60006129d2614411565b600d5460408051631f80982160e11b81526001600160a01b038085166004830152306024830152604482018a90529151939450911691633f0130429160648082019260009290919082900301818387803b158015612a2f57600080fd5b505af1158015612a43573d6000803e3d6000fd5b505050506124d68585858585614b52565b336000908152600e602052604090205460ff16612aa25760405162461bcd60e51b8152600401808060200182810382526022815260200180615b366022913960400191505060405180910390fd5b600b546001600160a01b0383811691161415612b05576040805162461bcd60e51b815260206004820152601f60248201527f63616e277420726573657420746865206d617374657220636f6e747261637400604482015290519081900360640190fd5b600d546001600160a01b0383811691161415612b68576040805162461bcd60e51b815260206004820152601f60248201527f63616e2774207265736574207468652065726337323120636f6e747261637400604482015290519081900360640190fd5b6001600160a01b038216612bc3576040805162461bcd60e51b815260206004820152601960248201527f63616e277420626520746865207a65726f206164647265737300000000000000604482015290519081900360640190fd5b6001600160a01b03919091166000908152600e60205260409020805460ff1916911515919091179055565b600b546001600160a01b03166317937a07612c07614411565b6040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b158015612c4657600080fd5b505af1158015612c5a573d6000803e3d6000fd5b505050506040513d6020811015612c7057600080fd5b5051612cad5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a656024913960400191505060405180910390fd5b612cb78282614db4565b5050565b600b546001600160a01b03166317937a07612cd4614411565b6040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b158015612d1357600080fd5b505af1158015612d27573d6000803e3d6000fd5b505050506040513d6020811015612d3d57600080fd5b5051612d7a5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a656024913960400191505060405180910390fd5b60008381526011602090815260408083206001600160a01b0386168452909152902054612da79082614b10565b60008481526011602090815260408083206001600160a01b0387168452909152812091909155612dd78484613ba2565b9050826001600160a01b0316847f4e6c02e9bc74e4cebedd8785daa9604431c9150d3deac966a5a71e937a228d0e846040518082815260200191505060405180910390a3612e23612f90565b60008581526014602090815260408083206001600160a01b03881680855290835281842054898552601284528285208286528452938290205482519485529284018690528382019290925251909187917f19f1796adcb2405f90c02fdd22577ab1e1bde3ba7966ccea9d3a3ea1f589287b9181900360600190a450505050565b6000806000806000612eb486614e61565b939850919650945092509050612ec9816149ba565b612f0f576040805162461bcd60e51b815260206004820152601260248201527136bab9ba1031329037b71030bab1ba34b7b760711b604482015290519081900360640190fd5b91939590929450565b601460209081526000928352604080842090915290825290205481565b600080612f4061200b565b905080611e8e576040805162461bcd60e51b8152602060048201526019602482015278636861696e204944206d757374206e6f74206265207a65726f60381b604482015290519081900360640190fd5b62093a8042635bb1637f19010490565b6001600160a01b031660009081526002602052604090205490565b600e6020526000908152604090205460ff1681565b600190565b601160209081526000928352604080842090915290825290205481565b601c5481565b62093a8081565b60068054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561197c5780601f106119515761010080835404028352916020019161197c565b6000818152601e60205260409020548060d081901c61307e816149ba565b6130ca576040805162461bcd60e51b81526020600482015260186024820152773a37b5b2b71036bab9ba1031329037b71030bab1ba34b7b760411b604482015290519081900360640190fd5b816001600160a01b03166130dc614411565b6001600160a01b031614611ffb576040805162461bcd60e51b815260206004820152601b60248201527f746f6b656e2073656c6c6572206d7573742062652073656e6465720000000000604482015290519081900360640190fd5b336000908152600f602052604090205460ff166131855760405162461bcd60e51b81526004018080602001828103825260338152602001806157fb6033913960400191505060405180910390fd5b6118eb838383614ea4565b600060028183156131a157836131a3565b305b6001600160a01b0316815260208101919091526040016000205492915050565b600c5481906001600160a01b031663110371ac826131df614411565b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b031681526020019250505060206040518083038186803b15801561322357600080fd5b505afa158015613237573d6000803e3d6000fd5b505050506040513d602081101561324d57600080fd5b50516132a0576040805162461bcd60e51b815260206004820152601b60248201527f73656e646572206d75737420626520612067616d652061646d696e0000000000604482015290519081900360640190fd5b600082116132df5760405162461bcd60e51b815260040180806020018281038252602481526020018061591d6024913960400191505060405180910390fd5b612cb7826132eb614411565b6001600160a01b0385166000908152600260205260409020546146ca565b600b546001600160a01b031663b4ff232e613322614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561335f57600080fd5b505afa158015613373573d6000803e3d6000fd5b505050506040513d602081101561338957600080fd5b50516133d5576040805162461bcd60e51b815260206004820152601660248201527573656e646572206d757374206265207468652063666f60501b604482015290519081900360640190fd5b6133f6306133e1614411565b306000908152600260205260409020546146ca565b565b60006119b0613405614411565b84611df085604051806060016040528060258152602001615c55602591396003600061342f614411565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190614827565b60008060008060008061347287614e61565b93985091965094509250905061348a84848484614fbb565b979650505050505050565b600b546001600160a01b031663b4ff232e6134ae614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156134eb57600080fd5b505afa1580156134ff573d6000803e3d6000fd5b505050506040513d602081101561351557600080fd5b5051613561576040805162461bcd60e51b815260206004820152601660248201527573656e646572206d757374206265207468652063666f60501b604482015290519081900360640190fd5b60648111156135b7576040805162461bcd60e51b815260206004820181905260248201527f6d757374206265206c657373207468616e206f7220657175616c20746f203125604482015290519081900360640190fd5b60188190556135d36135ca826006614ab7565b60195490614669565b601a5550565b60006119b06135e6614411565b84846146ca565b601e6020526000908152604090205481565b606061360961503b565b6136445760405162461bcd60e51b8152600401808060200182810382526042815260200180615ba66042913960600191505060405180910390fd5b61364c6156bc565b50604080516060810182528781526001600160a01b038916602082015290810186905261367c88828787876150b8565b6136b75760405162461bcd60e51b8152600401808060200182810382526021815260200180615a896021913960400191505060405180910390fd5b6001600160a01b03881660009081526009602090815260408083208a845290915290205460ff1615613730576040805162461bcd60e51b815260206004820181905260248201527f5245504c4159206f6620612070726576696f7573207472616e73616374696f6e604482015290519081900360640190fd5b6001600160a01b03881660008181526009602090815260408083208b84528252808320805460ff1916600117905580519384523384830181905260609185018281528b51928601929092528a517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b958e9592948d94919391926080850192918601918190849084905b838110156137d15781810151838201526020016137b9565b50505050905090810190601f1680156137fe5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a160006060306001600160a01b0316888b6040516020018083805190602001908083835b6020831061384f5780518252601f199092019160209182019101613830565b6001836020036101000a038019825116818451168082178552505050505050905001826001600160a01b031660601b8152601401925050506040516020818303038152906040526040518082805190602001908083835b602083106138c55780518252601f1990920191602091820191016138a6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613927576040519150601f19603f3d011682016040523d82523d6000602084013e61392c565b606091505b509150915081613983576040805162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c00000000604482015290519081900360640190fd5b9998505050505050505050565b601f6020526000908152604090205481565b601781815481106139af57fe5b600091825260209091200154905081565b600b546001600160a01b031663b4ff232e6139d9614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015613a1657600080fd5b505afa158015613a2a573d6000803e3d6000fd5b505050506040513d6020811015613a4057600080fd5b5051613a8c576040805162461bcd60e51b815260206004820152601660248201527573656e646572206d757374206265207468652063666f60501b604482015290519081900360640190fd5b60008060005b6007811015613b1357838160078110613aa757fe5b60200201359150828211613aec5760405162461bcd60e51b8152600401808060200182810382526023815260200180615be86023913960400191505060405180910390fd5b8160178281548110613afa57fe5b6000918252602090912001559091508190600101613a92565b508064174876e800146118eb576040805162461bcd60e51b815260206004820152601f60248201527f6869676865737420636170206d757374206265203130302062696c6c696f6e00604482015290519081900360640190fd5b60166020526000908152604090205481565b611f2f613b8a614411565b82614db4565b60156020526000908152604090205481565b60008281526013602090815260408083206001600160a01b038516845290915281205481613bce612f90565b60008681526014602090815260408083206001600160a01b038916845290915290205460105491925090613c4490613c1b90613c0b908490614a75565b613c158587614b10565b90614ab7565b60008881526011602090815260408083206001600160a01b038b16845290915290205490614669565b6001600160a01b0386166000908152601560205260409020549094508681148015613c6e57508615155b15613cdc576001600160a01b03861660009081526016602052604090205483811015613cda576001600160a01b03871660009081526002602052604081205490613cc9613cbb8785614b10565b601054613c15908590614a75565b9050613cd58882614669565b975050505b505b5050505092915050565b604051806080016040528060528152602001615976605291398051906020012081565b600a546001600160a01b031681565b601a5481565b60105481565b600b546001600160a01b031681565b600a546001600160a01b0316613d47614411565b6001600160a01b031614613d8c5760405162461bcd60e51b81526004018080602001828103825260248152602001806158a26024913960400191505060405180910390fd5b600082826020811015613d9e57600080fd5b5035905061200584826150e0565b600c546001600160a01b031681565b600d546001600160a01b031681565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b6040518060600160405280602581526020016157216025913981565b60185481565b336000908152600e602052604090205460ff16613e655760405162461bcd60e51b8152600401808060200182810382526022815260200180615b366022913960400191505060405180910390fd5b6118eb8383836146ca565b600b546001600160a01b0316632f54bf6e613e89614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015613ec657600080fd5b505afa158015613eda573d6000803e3d6000fd5b505050506040513d6020811015613ef057600080fd5b5051613f43576040805162461bcd60e51b815260206004820152601860248201527f73656e646572206d75737420626520746865206f776e65720000000000000000604482015290519081900360640190fd5b611f2f816151d2565b604051806040016040528060018152602001603160f81b81525081565b600b546001600160a01b031663b4ff232e613f82614411565b6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015613fbf57600080fd5b505afa158015613fd3573d6000803e3d6000fd5b505050506040513d6020811015613fe957600080fd5b5051614035576040805162461bcd60e51b815260206004820152601660248201527573656e646572206d757374206265207468652063666f60501b604482015290519081900360640190fd5b6101f481111561408c576040805162461bcd60e51b815260206004820181905260248201527f6d757374206265206c657373207468616e206f7220657175616c20746f203525604482015290519081900360640190fd5b60198190556018546135d3906140a3906006614ab7565b8290614669565b600b546001600160a01b03166317937a076140c3614411565b6040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b15801561410257600080fd5b505af1158015614116573d6000803e3d6000fd5b505050506040513d602081101561412c57600080fd5b50516131855760405162461bcd60e51b8152600401808060200182810382526024815260200180615a656024913960400191505060405180910390fd5b600080600080600061417a88614e61565b8095508196508297508398508499505050505050306001600160a01b0316600d60009054906101000a90046001600160a01b03166001600160a01b0316636352211e8a6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156141f157600080fd5b505afa158015614205573d6000803e3d6000fd5b505050506040513d602081101561421b57600080fd5b50516001600160a01b031614614278576040805162461bcd60e51b815260206004820152601f60248201527f636f6e7472616374206d757374206f776e206f6e2d73616c6520746f6b656e00604482015290519081900360640190fd5b614281816149ba565b6142c9576040805162461bcd60e51b815260206004820152601460248201527361756374696f6e206d757374206265206c69766560601b604482015290519081900360640190fd5b60006142d785858585614fbb565b9050808810156143185760405162461bcd60e51b815260040180806020018281038252602a815260200180615b58602a913960400191505060405180910390fd5b614321896151f4565b67ffffffffffffffff89166000614336614411565b905061434582848b8b85615212565b8a816001600160a01b0316896001600160a01b03167fb2f957e6e6ed6377e70534f97fc23756b916174a0228bf795ee7d21597c5f637866040518082815260200191505060405180910390a4600d5460408051631f80982160e11b81523060048201526001600160a01b038481166024830152604482018f905291519190921691633f01304291606480830192600092919082900301818387803b1580156143ec57600080fd5b505af1158015614400573d6000803e3d6000fd5b505050505050505050505050505050565b6000333014156144695760606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506119849050565b503390565b60008381526011602090815260408083206001600160a01b038616845290915290205461449b9082614669565b60008481526011602090815260408083206001600160a01b03871684529091528120919091556144cb8484613ba2565b9050612e23612f90565b6001600160a01b03831661451a5760405162461bcd60e51b8152600401808060200182810382526024815260200180615b826024913960400191505060405180910390fd5b6001600160a01b03821661455f5760405162461bcd60e51b81526004018080602001828103825260228152602001806157d96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260036020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006001600160a01b0386161580159061465f575060016145e96145e487615300565b615383565b83868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015614640573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b0316145b9695505050505050565b6000828201838110156146c3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b03831661470f5760405162461bcd60e51b8152600401808060200182810382526025815260200180615af16025913960400191505060405180910390fd5b6001600160a01b0382166147545760405162461bcd60e51b81526004018080602001828103825260238152602001806156dc6023913960400191505060405180910390fd5b61475f8383836153cf565b61479c8160405180606001604052806026815260200161582e602691396001600160a01b0386166000908152600260205260409020549190614827565b6001600160a01b0380851660009081526002602052604080822093909355908416815220546147cb9082614669565b6001600160a01b0380841660008181526002602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156148b65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561487b578181015183820152602001614863565b50505050905090810190601f1680156148a85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b0382166149035760405162461bcd60e51b8152600401808060200182810382526021815260200180615ad06021913960400191505060405180910390fd5b61490f826000836153cf565b61494c816040518060600160405280602281526020016156ff602291396001600160a01b0385166000908152600260205260409020549190614827565b6001600160a01b0383166000908152600260205260409020556004546149729082614b10565b6004556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b151590565b6149c8826151f4565b600d5460408051631f80982160e11b81523060048201526001600160a01b0384811660248301526044820186905291519190921691633f01304291606480830192600092919082900301818387803b158015614a2357600080fd5b505af1158015614a37573d6000803e3d6000fd5b50506040518492506001600160a01b03841691507f018b64b6242d32aa550e95d78985b938d71af5b3f10827b0683f55da1639304890600090a35050565b60006146c383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506154d1565b600082614ac6575060006119b4565b82820282848281614ad357fe5b04146146c35760405162461bcd60e51b8152600401808060200182810382526021815260200180615a1c6021913960400191505060405180910390fd5b60006146c383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614827565b8165ffffffffffff168214614b985760405162461bcd60e51b81526004018080602001828103825260268152602001806157466026913960400191505060405180910390fd5b836001600160801b03168414614bdf5760405162461bcd60e51b815260040180806020018281038252602a8152602001806157af602a913960400191505060405180910390fd5b826001600160801b03168314614c265760405162461bcd60e51b81526004018080602001828103825260288152602001806158546028913960400191505060405180910390fd5b60008411614c7b576040805162461bcd60e51b815260206004820152601f60248201527f7374617274696e67207072696365206d757374206265206e6f6e2d7a65726f00604482015290519081900360640190fd5b60008311614cd0576040805162461bcd60e51b815260206004820152601d60248201527f656e64696e67207072696365206d757374206265206e6f6e2d7a65726f000000604482015290519081900360640190fd5b603c821015614d105760405162461bcd60e51b8152600401808060200182810382526026815260200180615aaa6026913960400191505060405180910390fd5b6000858152601e602090815260408083204260d081901b6001600160d01b03191660a088901b6001600160a01b0388169081179190911792839055601f85529483902060808a811b8a179182905584518b81529586018a905285850192909252606085018890529251919492938a93927fabdd2430f9e10eb5db384c1218c42f980dd5fcda760a680a0d95ec506f0963cb929181900390910190a350505050505050565b614dbd82615536565b6001600160a01b038216600090815260156020908152604080832080549085905560169092528220549091614df0612f90565b905081614e13576001600160a01b03851660009081526016602052604090208190555b8383146124d6576040805182815290516001600160a01b0387169186917f48bf5c652deea67c8e1387e2003591e18b66d5b2a7642e6afd87efd825cbefae9181900360200190a35050505050565b6000908152601e6020908152604080832054601f909252909120549091608082901c916001600160801b03169065ffffffffffff60a085901c169060d085901c90565b6000614eb08484613ba2565b60008581526012602090815260408083206001600160a01b038816845290915281205491925090614ee19084614669565b905080821015614f225760405162461bcd60e51b815260040180806020018281038252602e8152602001806158c6602e913960400191505060405180910390fd5b60008581526012602090815260408083206001600160a01b03881684529091529020819055614f4f612f90565b60008681526014602090815260408083206001600160a01b038916808552908352928190205481519081529182018690528181018590525188917f19f1796adcb2405f90c02fdd22577ab1e1bde3ba7966ccea9d3a3ea1f589287b919081900360600190a45050505050565b6000614fc6826149ba565b61500c576040805162461bcd60e51b815260206004820152601260248201527136bab9ba1031329037b71030bab1ba34b7b760711b604482015290519081900360640190fd5b600082421115615023576150204284614b10565b90505b61502f868686846155d8565b9150505b949350505050565b600b54604080516317937a0760e01b815233600482015290516000926001600160a01b0316916317937a0791602480830192602092919082900301818787803b15801561508757600080fd5b505af115801561509b573d6000803e3d6000fd5b505050506040513d60208110156150b157600080fd5b5051905090565b60006001600160a01b0386161580159061465f575060016145e96150db87615605565b615688565b6001600160a01b03821661513b576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b615147600083836153cf565b6004546151549082614669565b6004556001600160a01b03821660009081526002602052604090205461517a9082614669565b6001600160a01b03831660008181526002602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601e60209081526040808320839055601f909152812055565b600061523561271061522f601a5488614ab790919063ffffffff16565b90614a75565b90506000615242876119ba565b905060006001600160a01b038616156152755761527061271061522f6019548a614ab790919063ffffffff16565b615278565b60005b9050600061529b61271061522f601854613c15878d614ab790919063ffffffff16565b905060006152b3826152ad8786614b10565b90614b10565b90506152c086888b6146ca565b6152cb8730836146ca565b6152e3878b156152db578b6152dd565b305b846146ca565b82156152f4576152f48789856146ca565b50505050505050505050565b600060405180608001604052806043815260200161576c60439139805190602001208260000151836020015184604001518051906020012060405160200180858152602001848152602001836001600160a01b03168152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b600061538d611d72565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b6001600160a01b03831615615450576001600160a01b0383166000908152600260205260409020547f134e340554ff8a7d64280a2a28b982df554e2595e5bf45cd39368f31099172a69084906154259084614b10565b604080516001600160a01b03909316835260208301919091528051918290030190a161545083615536565b6001600160a01b038216156118eb576001600160a01b0382166000908152600260205260409020547f134e340554ff8a7d64280a2a28b982df554e2595e5bf45cd39368f31099172a69083906154a69084614669565b604080516001600160a01b03909316835260208301919091528051918290030190a16118eb82615536565b600081836155205760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561487b578181015183820152602001614863565b50600083858161552c57fe5b0495945050505050565b6001600160a01b0381166000908152601560205260409020548015612cb7576001600160a01b03821660009081526016602052604081205490615577612f90565b905080821015612005576001600160a01b038416600090815260026020526040812054906155a8613cbb8486614b10565b90506155b585878361446e565b50506001600160a01b038416600090815260166020526040902081905550505050565b60008282106155e8575082615033565b848403600084848302816155f857fe5b0587019250615033915050565b60006040518060800160405280605481526020016159c860549139805190602001208260000151836020015184604001518051906020012060405160200180858152602001848152602001836001600160a01b03168152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b600061538d611d34565b60405180606001604052806000815260200160006001600160a01b03168152602001606081525090565b604080516060808201835260008083526020830152918101919091529056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636547414d4520437265646974732053696465636861696e20455243323020436f6e74726163746164642061756374696f6e3a206475726174696f6e206d75737420626520612075696e7434384d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e6174757265296164642061756374696f6e3a207374617274207072696365206d75737420626520612075696e7431323845524332303a20617070726f766520746f20746865207a65726f20616464726573736d75737420626520616e20617070726f766564204c6f79616c747920506f696e7473207370656e64657220636f6e747261637445524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63656164642061756374696f6e3a20656e64207072696365206d75737420626520612075696e743132387374617274696e67207072696365206d757374206265203e3d20656e64696e672070726963654368696c6445524332303a20494e53554646494349454e545f5045524d495353494f4e537370656e74206d6f7265204c6f79616c747920506f696e7473207468616e2063757272656e742062616c616e6365726571756573746564207765656b206d757374206265206e6f77206f7220696e20746865207061737463616e27742077697468647261772066726f6d20746865207a65726f2061646472657373726571756573746564207765656b206d75737420626520657175616c206f72206c61746572207468616e207374616b65207765656b454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429576f726b65724d6574615472616e73616374696f6e2862797465733332207265706c617950726576656e74696f6e2c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63656d7573742062652063616c6c6564206279206120776f726b6572206f72206d696e696f6e5369676e657220616e64207369676e617475726520646f206e6f74206d6174636861756374696f6e73206d7573742062652031206d696e757465206c6f6e67206f72206d6f726545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f20616464726573730c86b472d7e1cc408d1374136df3b65e32cf0d1d4f74e9ecfddb8dbcbf2513a66d7573742062652063616c6c65642062792061206c6f63616c20636f6e7472616374626964206d7573742062652067726561746572207468616e206f7220657175616c20746f20707269636545524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373576f726b6572204d6574612d5472616e73616374696f6e2073656e74206279206163636f756e74206f74686572207468616e206120776f726b65722f6d696e696f6e63617073206d75737420626520617363656e64696e6720616e64206e6f6e2d7a65726f436f6e74726163742069736e277420616e206578697374696e67207370656e6465726163636f756e74207374616b6520756e646572666c6f77202d206d757374206265203c313030426e45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ab6ee013fa41be9b39904f2c5a8d9a3c203391aa4d783260b0e126097037337a64736f6c6343000700003347414d4520437265646974732053696465636861696e20455243323020436f6e7472616374454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374290000000000000000000000002550aa5c84edb92a66125a85527c151923be35e1000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000002550aa5c84edb92a66125a85527c151923be35e1000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa

-----Decoded View---------------
Arg [0] : masterContract_ (address): 0x2550aa5c84edb92a66125a85527c151923be35e1
Arg [1] : depositor_ (address): 0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002550aa5c84edb92a66125a85527c151923be35e1
Arg [1] : 000000000000000000000000a6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.