Contract 0x8d1566569d5b695d44a9a234540f68D393cDC40D 2

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x109e2860b3b7d23bcf37656a4fde7326c21d0e3fbdc436e365bb818213237f94Approve336122302022-09-27 1:36:015 hrs 18 mins ago0x0f50ccd45abfb0cc2da7571c2169b0c82e8a6651 IN  GameCredits: GAME Token0 MATIC0.00349192575
0x043df55f7922b9d9ff257d76bc039fe4120dd55d61fe8c70e8d9f34650c85cc7Transfer335891932022-09-26 12:08:3218 hrs 45 mins ago0xd322a0bd6a139cfd359f1efc540f6cb358d73a16 IN  GameCredits: GAME Token0 MATIC0.00191020832
0xe150cc7fe0e9402dd25bee098a961c96650a42c7755db32635bb8aadb6e23e12Oracle Update St...335081062022-09-24 13:01:532 days 17 hrs ago0xed57f21aea3c1f0d153fc7c3ffa8647e9c810636 IN  GameCredits: GAME Token0 MATIC0.00563577841
0x807dcda024e52e4dfe48d7fc3eb9f18af36d9a14f673dde5cd72a369005fa667Oracle Update St...335080502022-09-24 12:59:572 days 17 hrs ago0xc258f4dca99364bda2cfc2361d76a7c437ab00e3 IN  GameCredits: GAME Token0 MATIC0.00563577841
0x215be91229c6ac70b59305f71c433046831f69355a92fca7f073edb5f5fdd76eOracle Update St...334829142022-09-23 22:23:453 days 8 hrs ago0xa43046ad18815278e27532f5d2659e8b8f98b88d IN  GameCredits: GAME Token0 MATIC0.00603727851
0x66523a638a1f10800f7d60e10412645a7f305d7067c4b0fd9f98efaf3158d5c0Approve334713022022-09-23 15:31:343 days 15 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.006985081886 150.026458614
0xb88787b344111d98b856548f9b500f3d0701997aabb7fc6459e470193b7fa4dfApprove334695582022-09-23 14:30:263 days 16 hrs ago0xced2a0e1c3d5b96d8cbead377b897f050b980574 IN  GameCredits: GAME Token0 MATIC0.006886660856147.91255948
0xd8688e07efc9e90a537475f08e66417a9c886aa7eafc2552c31a995ef333e748Approve334577102022-09-23 7:36:243 days 23 hrs ago0x1ae61cb1560a167bf66310da3d72d3b086c2e391 IN  GameCredits: GAME Token0 MATIC0.00139677 30.000000016
0x892f2322b1153da8ca59dc53f3dc31f4f824cbda9dd4cf111871755ca07b0dafApprove333587782022-09-20 21:49:106 days 9 hrs ago0x89a0fd76a948b14f546bbf771a4ffcfa5fffd533 IN  GameCredits: GAME Token0 MATIC0.00139641 30.000000011
0x7353d5b2d26e68412a7021184bf612e0c67370aea9e8b628a488c4c5f898f3daApprove333389432022-09-20 9:52:226 days 21 hrs ago0x1fb2a45e1c5253d6e7f6ae165b983636e8704680 IN  GameCredits: GAME Token0 MATIC0.001826827159 39.236821235
0xc3ce22f3439dccf264f50ced8806fbeb89e5b7e6ccb5bc0f4a8ffe2c10276c71Withdraw331822012022-09-16 14:55:2310 days 15 hrs ago0x5c5b24b4396e27fdfc2def6e4e6b9b063e65418d IN  GameCredits: GAME Token0 MATIC0.001750334684 52.457058917
0x39c25059c83d6a2bd49554041e73f3e2d6b7211392585d86c3ae62bac6756061Approve331702332022-09-16 7:59:1710 days 22 hrs ago0x5c5b24b4396e27fdfc2def6e4e6b9b063e65418d IN  GameCredits: GAME Token0 MATIC0.00133295 50.000000013
0x2a5326d073f05c085cf0d7894f009353b21080b22d7309eae82ed15f2310d04dApprove331701762022-09-16 7:57:2310 days 22 hrs ago0x5c5b24b4396e27fdfc2def6e4e6b9b063e65418d IN  GameCredits: GAME Token0 MATIC0.00147295 50.000000015
0x7eb5188f349ecee7407a87d793fa7fbedcb89cfed0715c28a65dad3415dd38eaApprove331701642022-09-16 7:56:5510 days 22 hrs ago0x5c5b24b4396e27fdfc2def6e4e6b9b063e65418d IN  GameCredits: GAME Token0 MATIC0.003009175 65.000000013
0x744205673046ce61e231e49e86c39fe56ead32081506cbaa869d6a85c0f9645dWithdraw330963302022-09-14 13:26:2012 days 17 hrs ago0x0ebccfcbca6249c6dec4f2bd0ab47c034ec659fd IN  GameCredits: GAME Token0 MATIC0.001001010001 30.000000033
0xf6028dca8202256bba480f10b8a541b0ba3a431046efcde3b7cea9ab76ffed30Approve330617612022-09-13 17:35:3213 days 13 hrs ago0xf85d965e9fd4607b000110253214f49231f0031a IN  GameCredits: GAME Token0 MATIC0.000791418041 32.602185015
0xe348359ff6e5ed676890ff67537e8f739ef06280ce1219264656a03b5d9f24a1Withdraw330554692022-09-13 13:58:5713 days 16 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.001685278404 50.507339729
0x1f0bb475dfc8bee29504e59c582ea778dc04f7c7d92a22a430a9c7c163414b6eTransfer330548342022-09-13 13:37:0713 days 17 hrs ago0xcc5f916c45e7a3506186fff370fb985ba93a5167 IN  GameCredits: GAME Token0 MATIC0.005576712643 101.523987684
0x2c91e3f73b116957f12aed5f2e77f170e5b9614b729c039ec99853217b415afdWithdraw330525082022-09-13 12:17:0813 days 18 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.001034243532 30.99600001
0x4e51b7cbc8fadd2c58ae7eab35770135a02ae5d0b8aa9b47b39ae58d926ca55dWithdraw330468562022-09-13 9:02:4013 days 21 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.00100101 30.000000022
0xe6f4c8058176bbb75fa9557c5267ed1ba3ab035fdf75c7e11f47649094fc41f1Withdraw330358432022-09-13 2:37:3614 days 4 hrs ago0xcc5f916c45e7a3506186fff370fb985ba93a5167 IN  GameCredits: GAME Token0 MATIC0.00228858 60.000000014
0x0af6763ab709694fa1d549885b6dfeddaa7cbc42626e054394b1dab05181612fWithdraw330352182022-09-13 2:16:0614 days 4 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.001349062163 35.368538484
0xfcd28ccee4f91beba77e0ae282df99869004dcf1093450340010fe421e24c7d0Withdraw330331242022-09-13 1:04:0614 days 5 hrs ago0x0ebccfcbca6249c6dec4f2bd0ab47c034ec659fd IN  GameCredits: GAME Token0 MATIC0.001209887419 36.259999993
0x0914bbe96279c4f580ba3a06244a995bcd96b35a472f6d39f06c4453c0eab2edWithdraw330314562022-09-13 0:05:5614 days 6 hrs ago0x38b762fc4d538efd9addefd4f6dae8472ffd9b74 IN  GameCredits: GAME Token0 MATIC0.001043306946 31.267628089
0xb3ecdbbd1cc67a388d352f157448fae801362b48ef6b1aa15d14d628f340b236Withdraw330276682022-09-12 21:51:2214 days 9 hrs ago0x3b27da2147e82df01af28243e67a684794ce0268 IN  GameCredits: GAME Token0 MATIC0.001134345071 33.996016179
[ 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:09154 days 23 hrs ago 0x9d7dc4925885619c546b56e2698afef8fb37bc6c GameCredits: GAME Token0 MATIC
0x5920f17f7db22b278ba81dfb487796f493938f865bb38dbed4d5d7ba34265f44268563392022-04-07 15:25:39172 days 15 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.