ETH Price: $3,677.14 (+1.02%)

Token

pNetwork Token (PNT)
 

Overview

Max Total Supply

87,972,987.722997040030171772 PNT

Holders

10,829 (0.00%)

Market

Price

$0.01 @ 0.000001 ETH (-5.16%)

Onchain Market Cap

$462,550.53

Circulating Supply Market Cap

$462,073.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
91 PNT

Value
$0.48 ( ~0.000130536222304928 Eth) [0.0001%]
0xB7a1B79Af32A230F8A37f22cb3f97fEF8dE387Bc
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

pNetwork is the heartbeat of cross-chain composability. As the governance network for the pTokens system, it enables the seamless movement of assets across blockchains.

Market

Volume (24H):$7,071.38
Market Capitalization:$462,073.00
Circulating Supply:87,920,342.00 PNT
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
PNT

Compiler Version
v0.6.10+commit.00c0fcaf

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-06-17
*/

// File: @openzeppelin/contracts/GSN/Context.sol

pragma solidity ^0.6.0;

/*
 * @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.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }

    function _msgSender() internal view virtual returns (address payable) {
        return msg.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;
    }
}

// File: @openzeppelin/contracts/token/ERC777/IERC777.sol

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(address recipient, uint256 amount, bytes calldata data) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );

    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    event RevokedOperator(address indexed operator, address indexed tokenHolder);
}

// File: @openzeppelin/contracts/token/ERC777/IERC777Recipient.sol

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
 *
 * Accounts can be notified of {IERC777} tokens being sent to them by having a
 * contract implement this interface (contract holders can be their own
 * implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Recipient {
    /**
     * @dev Called by an {IERC777} token contract whenever tokens are being
     * moved or created into a registered account (`to`). The type of operation
     * is conveyed by `from` being the zero address or not.
     *
     * This call occurs _after_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

// File: @openzeppelin/contracts/token/ERC777/IERC777Sender.sol

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777TokensSender standard as defined in the EIP.
 *
 * {IERC777} Token holders can be notified of operations performed on their
 * tokens by having a contract implement this interface (contract holders can be
 *  their own implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Sender {
    /**
     * @dev Called by an {IERC777} token contract whenever a registered holder's
     * (`from`) tokens are about to be moved or destroyed. The type of operation
     * is conveyed by `to` being the zero address or not.
     *
     * This call occurs _before_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the pre-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol

pragma solidity ^0.6.0;

/**
 * @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);
}

// File: @openzeppelin/contracts/math/SafeMath.sol

pragma solidity ^0.6.0;

/**
 * @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) {
        // Solidity only automatically asserts when dividing by 0
        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;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol

pragma solidity ^0.6.2;

/**
 * @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) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @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");
    }
}

// File: @openzeppelin/contracts/introspection/IERC1820Registry.sol

pragma solidity ^0.6.0;

/**
 * @dev Interface of the global ERC1820 Registry, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
 * implementers for interfaces in this registry, as well as query support.
 *
 * Implementers may be shared by multiple accounts, and can also implement more
 * than a single interface for each account. Contracts can implement interfaces
 * for themselves, but externally-owned accounts (EOA) must delegate this to a
 * contract.
 *
 * {IERC165} interfaces can also be queried via the registry.
 *
 * For an in-depth explanation and source code analysis, see the EIP text.
 */
interface IERC1820Registry {
    /**
     * @dev Sets `newManager` as the manager for `account`. A manager of an
     * account is able to set interface implementers for it.
     *
     * By default, each account is its own manager. Passing a value of `0x0` in
     * `newManager` will reset the manager to this initial state.
     *
     * Emits a {ManagerChanged} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     */
    function setManager(address account, address newManager) external;

    /**
     * @dev Returns the manager for `account`.
     *
     * See {setManager}.
     */
    function getManager(address account) external view returns (address);

    /**
     * @dev Sets the `implementer` contract as ``account``'s implementer for
     * `interfaceHash`.
     *
     * `account` being the zero address is an alias for the caller's address.
     * The zero address can also be used in `implementer` to remove an old one.
     *
     * See {interfaceHash} to learn how these are created.
     *
     * Emits an {InterfaceImplementerSet} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
     * end in 28 zeroes).
     * - `implementer` must implement {IERC1820Implementer} and return true when
     * queried for support, unless `implementer` is the caller. See
     * {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;

    /**
     * @dev Returns the implementer of `interfaceHash` for `account`. If no such
     * implementer is registered, returns the zero address.
     *
     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
     * zeroes), `account` will be queried for support of it.
     *
     * `account` being the zero address is an alias for the caller's address.
     */
    function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);

    /**
     * @dev Returns the interface hash for an `interfaceName`, as defined in the
     * corresponding
     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
     */
    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);

    /**
     *  @notice Updates the cache with whether the contract implements an ERC165 interface or not.
     *  @param account Address of the contract for which to update the cache.
     *  @param interfaceId ERC165 interface for which to update the cache.
     */
    function updateERC165Cache(address account, bytes4 interfaceId) external;

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not.
     *  If the result is not cached a direct lookup on the contract address is performed.
     *  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
     *  {updateERC165Cache} with the contract address.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);

    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);

    event ManagerChanged(address indexed account, address indexed newManager);
}

// File: @openzeppelin/contracts/token/ERC777/ERC777.sol

pragma solidity ^0.6.0;









/**
 * @dev Implementation of the {IERC777} 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}.
 *
 * Support for ERC20 is included in this contract, as specified by the EIP: both
 * the ERC777 and ERC20 interfaces can be safely used when interacting with it.
 * Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
 * movements.
 *
 * Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
 * are no special restrictions in the amount of tokens that created, moved, or
 * destroyed. This makes integration with ERC20 applications seamless.
 */
contract ERC777 is Context, IERC777, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

    mapping(address => uint256) private _balances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    // We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
    // See https://github.com/ethereum/solidity/issues/4024.

    // keccak256("ERC777TokensSender")
    bytes32 constant private _TOKENS_SENDER_INTERFACE_HASH =
        0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;

    // keccak256("ERC777TokensRecipient")
    bytes32 constant private _TOKENS_RECIPIENT_INTERFACE_HASH =
        0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;

    // This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

    // For each account, a mapping of its operators and revoked default operators.
    mapping(address => mapping(address => bool)) private _operators;
    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;

    // ERC20-allowances
    mapping (address => mapping (address => uint256)) private _allowances;

    /**
     * @dev `defaultOperators` may be an empty array.
     */
    constructor(
        string memory name,
        string memory symbol,
        address[] memory defaultOperators
    ) public {
        _name = name;
        _symbol = symbol;

        _defaultOperatorsArray = defaultOperators;
        for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
            _defaultOperators[_defaultOperatorsArray[i]] = true;
        }

        // register interfaces
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
    }

    /**
     * @dev See {IERC777-name}.
     */
    function name() public view override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC777-symbol}.
     */
    function symbol() public view override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {ERC20-decimals}.
     *
     * Always returns 18, as per the
     * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
     */
    function decimals() public pure returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC777-granularity}.
     *
     * This implementation always returns `1`.
     */
    function granularity() public view override returns (uint256) {
        return 1;
    }

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

    /**
     * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
     */
    function balanceOf(address tokenHolder) public view override(IERC20, IERC777) returns (uint256) {
        return _balances[tokenHolder];
    }

    /**
     * @dev See {IERC777-send}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function send(address recipient, uint256 amount, bytes memory data) public override  {
        _send(_msgSender(), recipient, amount, data, "", true);
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
     * interface if it is a contract.
     *
     * Also emits a {Sent} event.
     */
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        require(recipient != address(0), "ERC777: transfer to the zero address");

        address from = _msgSender();

        _callTokensToSend(from, from, recipient, amount, "", "");

        _move(from, from, recipient, amount, "", "");

        _callTokensReceived(from, from, recipient, amount, "", "", false);

        return true;
    }

    /**
     * @dev See {IERC777-burn}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function burn(uint256 amount, bytes memory data) public override  {
        _burn(_msgSender(), amount, data, "");
    }

    /**
     * @dev See {IERC777-isOperatorFor}.
     */
    function isOperatorFor(
        address operator,
        address tokenHolder
    ) public view override returns (bool) {
        return operator == tokenHolder ||
            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
            _operators[tokenHolder][operator];
    }

    /**
     * @dev See {IERC777-authorizeOperator}.
     */
    function authorizeOperator(address operator) public override  {
        require(_msgSender() != operator, "ERC777: authorizing self as operator");

        if (_defaultOperators[operator]) {
            delete _revokedDefaultOperators[_msgSender()][operator];
        } else {
            _operators[_msgSender()][operator] = true;
        }

        emit AuthorizedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-revokeOperator}.
     */
    function revokeOperator(address operator) public override  {
        require(operator != _msgSender(), "ERC777: revoking self as operator");

        if (_defaultOperators[operator]) {
            _revokedDefaultOperators[_msgSender()][operator] = true;
        } else {
            delete _operators[_msgSender()][operator];
        }

        emit RevokedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-defaultOperators}.
     */
    function defaultOperators() public view override returns (address[] memory) {
        return _defaultOperatorsArray;
    }

    /**
     * @dev See {IERC777-operatorSend}.
     *
     * Emits {Sent} and {IERC20-Transfer} events.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
    public override
    {
        require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
        _send(sender, recipient, amount, data, operatorData, true);
    }

    /**
     * @dev See {IERC777-operatorBurn}.
     *
     * Emits {Burned} and {IERC20-Transfer} events.
     */
    function operatorBurn(address account, uint256 amount, bytes memory data, bytes memory operatorData) public override {
        require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
        _burn(account, amount, data, operatorData);
    }

    /**
     * @dev See {IERC20-allowance}.
     *
     * Note that operator and allowance concepts are orthogonal: operators may
     * not have allowance, and accounts with allowance may not be operators
     * themselves.
     */
    function allowance(address holder, address spender) public view override returns (uint256) {
        return _allowances[holder][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Note that accounts cannot have allowance issued by their operators.
     */
    function approve(address spender, uint256 value) public override returns (bool) {
        address holder = _msgSender();
        _approve(holder, spender, value);
        return true;
    }

   /**
    * @dev See {IERC20-transferFrom}.
    *
    * Note that operator and allowance concepts are orthogonal: operators cannot
    * call `transferFrom` (unless they have allowance), and accounts with
    * allowance cannot call `operatorSend` (unless they are operators).
    *
    * Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.
    */
    function transferFrom(address holder, address recipient, uint256 amount) public override returns (bool) {
        require(recipient != address(0), "ERC777: transfer to the zero address");
        require(holder != address(0), "ERC777: transfer from the zero address");

        address spender = _msgSender();

        _callTokensToSend(spender, holder, recipient, amount, "", "");

        _move(spender, holder, recipient, amount, "", "");
        _approve(holder, spender, _allowances[holder][spender].sub(amount, "ERC777: transfer amount exceeds allowance"));

        _callTokensReceived(spender, holder, recipient, amount, "", "", false);

        return true;
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `operator`, `data` and `operatorData`.
     *
     * See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits {Minted} and {IERC20-Transfer} events.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - if `account` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function _mint(
        address account,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    internal virtual
    {
        require(account != address(0), "ERC777: mint to the zero address");

        address operator = _msgSender();

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

        // Update state variables
        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);

        _callTokensReceived(operator, address(0), account, amount, userData, operatorData, true);

        emit Minted(operator, account, amount, userData, operatorData);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Send tokens
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _send(
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
        internal
    {
        require(from != address(0), "ERC777: send from the zero address");
        require(to != address(0), "ERC777: send to the zero address");

        address operator = _msgSender();

        _callTokensToSend(operator, from, to, amount, userData, operatorData);

        _move(operator, from, to, amount, userData, operatorData);

        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
    }

    /**
     * @dev Burn tokens
     * @param from address token holder address
     * @param amount uint256 amount of tokens to burn
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _burn(
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
        internal virtual
    {
        require(from != address(0), "ERC777: burn from the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, address(0), amount);

        _callTokensToSend(operator, from, address(0), amount, data, operatorData);

        // Update state variables
        _balances[from] = _balances[from].sub(amount, "ERC777: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);

        emit Burned(operator, from, amount, data, operatorData);
        emit Transfer(from, address(0), amount);
    }

    function _move(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
        private
    {
        _beforeTokenTransfer(operator, from, to, amount);

        _balances[from] = _balances[from].sub(amount, "ERC777: transfer amount exceeds balance");
        _balances[to] = _balances[to].add(amount);

        emit Sent(operator, from, to, amount, userData, operatorData);
        emit Transfer(from, to, amount);
    }

    /**
     * @dev See {ERC20-_approve}.
     *
     * Note that accounts cannot have allowance issued by their operators.
     */
    function _approve(address holder, address spender, uint256 value) internal {
        require(holder != address(0), "ERC777: approve from the zero address");
        require(spender != address(0), "ERC777: approve to the zero address");

        _allowances[holder][spender] = value;
        emit Approval(holder, spender, value);
    }

    /**
     * @dev Call from.tokensToSend() if the interface is registered
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _callTokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
        private
    {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
        }
    }

    /**
     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
     * tokensReceived() was not registered for the recipient
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
        private
    {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes
     * calls to {send}, {transfer}, {operatorSend}, minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - when `from` is zero, `tokenId` will be minted for `to`.
     * - when `to` is zero, ``from``'s `tokenId` 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 operator, address from, address to, uint256 tokenId) internal virtual { }
}

// File: @openzeppelin/contracts/access/Ownable.sol

pragma solidity ^0.6.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// File: @openzeppelin/contracts/GSN/IRelayRecipient.sol

pragma solidity ^0.6.0;

/**
 * @dev Base interface for a contract that will be called via the GSN from {IRelayHub}.
 *
 * TIP: You don't need to write an implementation yourself! Inherit from {GSNRecipient} instead.
 */
interface IRelayRecipient {
    /**
     * @dev Returns the address of the {IRelayHub} instance this recipient interacts with.
     */
    function getHubAddr() external view returns (address);

    /**
     * @dev Called by {IRelayHub} to validate if this recipient accepts being charged for a relayed call. Note that the
     * recipient will be charged regardless of the execution result of the relayed call (i.e. if it reverts or not).
     *
     * The relay request was originated by `from` and will be served by `relay`. `encodedFunction` is the relayed call
     * calldata, so its first four bytes are the function selector. The relayed call will be forwarded `gasLimit` gas,
     * and the transaction executed with a gas price of at least `gasPrice`. ``relay``'s fee is `transactionFee`, and the
     * recipient will be charged at most `maxPossibleCharge` (in wei). `nonce` is the sender's (`from`) nonce for
     * replay attack protection in {IRelayHub}, and `approvalData` is a optional parameter that can be used to hold a signature
     * over all or some of the previous values.
     *
     * Returns a tuple, where the first value is used to indicate approval (0) or rejection (custom non-zero error code,
     * values 1 to 10 are reserved) and the second one is data to be passed to the other {IRelayRecipient} functions.
     *
     * {acceptRelayedCall} is called with 50k gas: if it runs out during execution, the request will be considered
     * rejected. A regular revert will also trigger a rejection.
     */
    function acceptRelayedCall(
        address relay,
        address from,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata approvalData,
        uint256 maxPossibleCharge
    )
        external
        view
        returns (uint256, bytes memory);

    /**
     * @dev Called by {IRelayHub} on approved relay call requests, before the relayed call is executed. This allows to e.g.
     * pre-charge the sender of the transaction.
     *
     * `context` is the second value returned in the tuple by {acceptRelayedCall}.
     *
     * Returns a value to be passed to {postRelayedCall}.
     *
     * {preRelayedCall} is called with 100k gas: if it runs out during exection or otherwise reverts, the relayed call
     * will not be executed, but the recipient will still be charged for the transaction's cost.
     */
    function preRelayedCall(bytes calldata context) external returns (bytes32);

    /**
     * @dev Called by {IRelayHub} on approved relay call requests, after the relayed call is executed. This allows to e.g.
     * charge the user for the relayed call costs, return any overcharges from {preRelayedCall}, or perform
     * contract-specific bookkeeping.
     *
     * `context` is the second value returned in the tuple by {acceptRelayedCall}. `success` is the execution status of
     * the relayed call. `actualCharge` is an estimate of how much the recipient will be charged for the transaction,
     * not including any gas used by {postRelayedCall} itself. `preRetVal` is {preRelayedCall}'s return value.
     *
     *
     * {postRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call
     * and the call to {preRelayedCall} will be reverted retroactively, but the recipient will still be charged for the
     * transaction's cost.
     */
    function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external;
}

// File: @openzeppelin/contracts/GSN/IRelayHub.sol

pragma solidity ^0.6.0;

/**
 * @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
 * directly.
 *
 * See the https://github.com/OpenZeppelin/openzeppelin-gsn-helpers[OpenZeppelin GSN helpers] for more information on
 * how to deploy an instance of `RelayHub` on your local test network.
 */
interface IRelayHub {
    // Relay management

    /**
     * @dev Adds stake to a relay and sets its `unstakeDelay`. If the relay does not exist, it is created, and the caller
     * of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
     * cannot be its own owner.
     *
     * All Ether in this function call will be added to the relay's stake.
     * Its unstake delay will be assigned to `unstakeDelay`, but the new value must be greater or equal to the current one.
     *
     * Emits a {Staked} event.
     */
    function stake(address relayaddr, uint256 unstakeDelay) external payable;

    /**
     * @dev Emitted when a relay's stake or unstakeDelay are increased
     */
    event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);

    /**
     * @dev Registers the caller as a relay.
     * The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
     *
     * This function can be called multiple times, emitting new {RelayAdded} events. Note that the received
     * `transactionFee` is not enforced by {relayCall}.
     *
     * Emits a {RelayAdded} event.
     */
    function registerRelay(uint256 transactionFee, string calldata url) external;

    /**
     * @dev Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out
     * {RelayRemoved} events) lets a client discover the list of available relays.
     */
    event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);

    /**
     * @dev Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed.
     *
     * Can only be called by the owner of the relay. After the relay's `unstakeDelay` has elapsed, {unstake} will be
     * callable.
     *
     * Emits a {RelayRemoved} event.
     */
    function removeRelayByOwner(address relay) external;

    /**
     * @dev Emitted when a relay is removed (deregistered). `unstakeTime` is the time when unstake will be callable.
     */
    event RelayRemoved(address indexed relay, uint256 unstakeTime);

    /** Deletes the relay from the system, and gives back its stake to the owner.
     *
     * Can only be called by the relay owner, after `unstakeDelay` has elapsed since {removeRelayByOwner} was called.
     *
     * Emits an {Unstaked} event.
     */
    function unstake(address relay) external;

    /**
     * @dev Emitted when a relay is unstaked for, including the returned stake.
     */
    event Unstaked(address indexed relay, uint256 stake);

    // States a relay can be in
    enum RelayState {
        Unknown, // The relay is unknown to the system: it has never been staked for
        Staked, // The relay has been staked for, but it is not yet active
        Registered, // The relay has registered itself, and is active (can relay calls)
        Removed    // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake
    }

    /**
     * @dev Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function
     * to return an empty entry.
     */
    function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);

    // Balance management

    /**
     * @dev Deposits Ether for a contract, so that it can receive (and pay for) relayed transactions.
     *
     * Unused balance can only be withdrawn by the contract itself, by calling {withdraw}.
     *
     * Emits a {Deposited} event.
     */
    function depositFor(address target) external payable;

    /**
     * @dev Emitted when {depositFor} is called, including the amount and account that was funded.
     */
    event Deposited(address indexed recipient, address indexed from, uint256 amount);

    /**
     * @dev Returns an account's deposits. These can be either a contracts's funds, or a relay owner's revenue.
     */
    function balanceOf(address target) external view returns (uint256);

    /**
     * Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
     * contracts can use it to reduce their funding.
     *
     * Emits a {Withdrawn} event.
     */
    function withdraw(uint256 amount, address payable dest) external;

    /**
     * @dev Emitted when an account withdraws funds from `RelayHub`.
     */
    event Withdrawn(address indexed account, address indexed dest, uint256 amount);

    // Relaying

    /**
     * @dev Checks if the `RelayHub` will accept a relayed operation.
     * Multiple things must be true for this to happen:
     *  - all arguments must be signed for by the sender (`from`)
     *  - the sender's nonce must be the current one
     *  - the recipient must accept this transaction (via {acceptRelayedCall})
     *
     * Returns a `PreconditionCheck` value (`OK` when the transaction can be relayed), or a recipient-specific error
     * code if it returns one in {acceptRelayedCall}.
     */
    function canRelay(
        address relay,
        address from,
        address to,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata signature,
        bytes calldata approvalData
    ) external view returns (uint256 status, bytes memory recipientContext);

    // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
    enum PreconditionCheck {
        OK,                         // All checks passed, the call can be relayed
        WrongSignature,             // The transaction to relay is not signed by requested sender
        WrongNonce,                 // The provided nonce has already been used by the sender
        AcceptRelayedCallReverted,  // The recipient rejected this call via acceptRelayedCall
        InvalidRecipientStatusCode  // The recipient returned an invalid (reserved) status code
    }

    /**
     * @dev Relays a transaction.
     *
     * For this to succeed, multiple conditions must be met:
     *  - {canRelay} must `return PreconditionCheck.OK`
     *  - the sender must be a registered relay
     *  - the transaction's gas price must be larger or equal to the one that was requested by the sender
     *  - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
     * recipient) use all gas available to them
     *  - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
     * spent)
     *
     * If all conditions are met, the call will be relayed and the recipient charged. {preRelayedCall}, the encoded
     * function and {postRelayedCall} will be called in that order.
     *
     * Parameters:
     *  - `from`: the client originating the request
     *  - `to`: the target {IRelayRecipient} contract
     *  - `encodedFunction`: the function call to relay, including data
     *  - `transactionFee`: fee (%) the relay takes over actual gas cost
     *  - `gasPrice`: gas price the client is willing to pay
     *  - `gasLimit`: gas to forward when calling the encoded function
     *  - `nonce`: client's nonce
     *  - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses
     *  - `approvalData`: dapp-specific data forwared to {acceptRelayedCall}. This value is *not* verified by the
     * `RelayHub`, but it still can be used for e.g. a signature.
     *
     * Emits a {TransactionRelayed} event.
     */
    function relayCall(
        address from,
        address to,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata signature,
        bytes calldata approvalData
    ) external;

    /**
     * @dev Emitted when an attempt to relay a call failed.
     *
     * This can happen due to incorrect {relayCall} arguments, or the recipient not accepting the relayed call. The
     * actual relayed call was not executed, and the recipient not charged.
     *
     * The `reason` parameter contains an error code: values 1-10 correspond to `PreconditionCheck` entries, and values
     * over 10 are custom recipient error codes returned from {acceptRelayedCall}.
     */
    event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);

    /**
     * @dev Emitted when a transaction is relayed.
     * Useful when monitoring a relay's operation and relayed calls to a contract
     *
     * Note that the actual encoded function might be reverted: this is indicated in the `status` parameter.
     *
     * `charge` is the Ether value deducted from the recipient's balance, paid to the relay's owner.
     */
    event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);

    // Reason error codes for the TransactionRelayed event
    enum RelayCallStatus {
        OK,                      // The transaction was successfully relayed and execution successful - never included in the event
        RelayedCallFailed,       // The transaction was relayed, but the relayed call failed
        PreRelayedFailed,        // The transaction was not relayed due to preRelatedCall reverting
        PostRelayedFailed,       // The transaction was relayed and reverted due to postRelatedCall reverting
        RecipientBalanceChanged  // The transaction was relayed and reverted due to the recipient's balance changing
    }

    /**
     * @dev Returns how much gas should be forwarded to a call to {relayCall}, in order to relay a transaction that will
     * spend up to `relayedCallStipend` gas.
     */
    function requiredGas(uint256 relayedCallStipend) external view returns (uint256);

    /**
     * @dev Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
     */
    function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256);

     // Relay penalization.
     // Any account can penalize relays, removing them from the system immediately, and rewarding the
    // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
    // still loses half of its stake.

    /**
     * @dev Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
     * different data (gas price, gas limit, etc. may be different).
     *
     * The (unsigned) transaction data and signature for both transactions must be provided.
     */
    function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external;

    /**
     * @dev Penalize a relay that sent a transaction that didn't target ``RelayHub``'s {registerRelay} or {relayCall}.
     */
    function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external;

    /**
     * @dev Emitted when a relay is penalized.
     */
    event Penalized(address indexed relay, address sender, uint256 amount);

    /**
     * @dev Returns an account's nonce in `RelayHub`.
     */
    function getNonce(address from) external view returns (uint256);
}

// File: @openzeppelin/contracts/GSN/GSNRecipient.sol

pragma solidity ^0.6.0;




/**
 * @dev Base GSN recipient contract: includes the {IRelayRecipient} interface
 * and enables GSN support on all contracts in the inheritance tree.
 *
 * TIP: This contract is abstract. The functions {IRelayRecipient-acceptRelayedCall},
 *  {_preRelayedCall}, and {_postRelayedCall} are not implemented and must be
 * provided by derived contracts. See the
 * xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategies] for more
 * information on how to use the pre-built {GSNRecipientSignature} and
 * {GSNRecipientERC20Fee}, or how to write your own.
 */
abstract contract GSNRecipient is IRelayRecipient, Context {
    // Default RelayHub address, deployed on mainnet and all testnets at the same address
    address private _relayHub = 0xD216153c06E857cD7f72665E0aF1d7D82172F494;

    uint256 constant private _RELAYED_CALL_ACCEPTED = 0;
    uint256 constant private _RELAYED_CALL_REJECTED = 11;

    // How much gas is forwarded to postRelayedCall
    uint256 constant internal _POST_RELAYED_CALL_MAX_GAS = 100000;

    /**
     * @dev Emitted when a contract changes its {IRelayHub} contract to a new one.
     */
    event RelayHubChanged(address indexed oldRelayHub, address indexed newRelayHub);

    /**
     * @dev Returns the address of the {IRelayHub} contract for this recipient.
     */
    function getHubAddr() public view override returns (address) {
        return _relayHub;
    }

    /**
     * @dev Switches to a new {IRelayHub} instance. This method is added for future-proofing: there's no reason to not
     * use the default instance.
     *
     * IMPORTANT: After upgrading, the {GSNRecipient} will no longer be able to receive relayed calls from the old
     * {IRelayHub} instance. Additionally, all funds should be previously withdrawn via {_withdrawDeposits}.
     */
    function _upgradeRelayHub(address newRelayHub) internal virtual {
        address currentRelayHub = _relayHub;
        require(newRelayHub != address(0), "GSNRecipient: new RelayHub is the zero address");
        require(newRelayHub != currentRelayHub, "GSNRecipient: new RelayHub is the current one");

        emit RelayHubChanged(currentRelayHub, newRelayHub);

        _relayHub = newRelayHub;
    }

    /**
     * @dev Returns the version string of the {IRelayHub} for which this recipient implementation was built. If
     * {_upgradeRelayHub} is used, the new {IRelayHub} instance should be compatible with this version.
     */
    // This function is view for future-proofing, it may require reading from
    // storage in the future.
    function relayHubVersion() public view returns (string memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return "1.0.0";
    }

    /**
     * @dev Withdraws the recipient's deposits in `RelayHub`.
     *
     * Derived contracts should expose this in an external interface with proper access control.
     */
    function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
        IRelayHub(_relayHub).withdraw(amount, payee);
    }

    // Overrides for Context's functions: when called from RelayHub, sender and
    // data require some pre-processing: the actual sender is stored at the end
    // of the call data, which in turns means it needs to be removed from it
    // when handling said data.

    /**
     * @dev Replacement for msg.sender. Returns the actual sender of a transaction: msg.sender for regular transactions,
     * and the end-user for GSN relayed calls (where msg.sender is actually `RelayHub`).
     *
     * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
     */
    function _msgSender() internal view virtual override returns (address payable) {
        if (msg.sender != _relayHub) {
            return msg.sender;
        } else {
            return _getRelayedCallSender();
        }
    }

    /**
     * @dev Replacement for msg.data. Returns the actual calldata of a transaction: msg.data for regular transactions,
     * and a reduced version for GSN relayed calls (where msg.data contains additional information).
     *
     * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
     */
    function _msgData() internal view virtual override returns (bytes memory) {
        if (msg.sender != _relayHub) {
            return msg.data;
        } else {
            return _getRelayedCallData();
        }
    }

    // Base implementations for pre and post relayedCall: only RelayHub can invoke them, and data is forwarded to the
    // internal hook.

    /**
     * @dev See `IRelayRecipient.preRelayedCall`.
     *
     * This function should not be overriden directly, use `_preRelayedCall` instead.
     *
     * * Requirements:
     *
     * - the caller must be the `RelayHub` contract.
     */
    function preRelayedCall(bytes memory context) public virtual override returns (bytes32) {
        require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
        return _preRelayedCall(context);
    }

    /**
     * @dev See `IRelayRecipient.preRelayedCall`.
     *
     * Called by `GSNRecipient.preRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts
     * must implement this function with any relayed-call preprocessing they may wish to do.
     *
     */
    function _preRelayedCall(bytes memory context) internal virtual returns (bytes32);

    /**
     * @dev See `IRelayRecipient.postRelayedCall`.
     *
     * This function should not be overriden directly, use `_postRelayedCall` instead.
     *
     * * Requirements:
     *
     * - the caller must be the `RelayHub` contract.
     */
    function postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) public virtual override {
        require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
        _postRelayedCall(context, success, actualCharge, preRetVal);
    }

    /**
     * @dev See `IRelayRecipient.postRelayedCall`.
     *
     * Called by `GSNRecipient.postRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts
     * must implement this function with any relayed-call postprocessing they may wish to do.
     *
     */
    function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal virtual;

    /**
     * @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
     * will be charged a fee by RelayHub
     */
    function _approveRelayedCall() internal pure returns (uint256, bytes memory) {
        return _approveRelayedCall("");
    }

    /**
     * @dev See `GSNRecipient._approveRelayedCall`.
     *
     * This overload forwards `context` to _preRelayedCall and _postRelayedCall.
     */
    function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
        return (_RELAYED_CALL_ACCEPTED, context);
    }

    /**
     * @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
     */
    function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
        return (_RELAYED_CALL_REJECTED + errorCode, "");
    }

    /*
     * @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's
     * `serviceFee`.
     */
    function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) {
        // The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be
        // charged for 1.4 times the spent amount.
        return (gas * gasPrice * (100 + serviceFee)) / 100;
    }

    function _getRelayedCallSender() private pure returns (address payable result) {
        // We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array
        // is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing
        // so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would
        // require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20
        // bytes. This can always be done due to the 32-byte prefix.

        // The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the
        // easiest/most-efficient way to perform this operation.

        // These fields are not accessible from assembly
        bytes memory array = msg.data;
        uint256 index = msg.data.length;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
        return result;
    }

    function _getRelayedCallData() private pure returns (bytes memory) {
        // RelayHub appends the sender address at the end of the calldata, so in order to retrieve the actual msg.data,
        // we must strip the last 20 bytes (length of an address type) from it.

        uint256 actualDataLength = msg.data.length - 20;
        bytes memory actualData = new bytes(actualDataLength);

        for (uint256 i = 0; i < actualDataLength; ++i) {
            actualData[i] = msg.data[i];
        }

        return actualData;
    }
}

// File: @openzeppelin/contracts/cryptography/ECDSA.sol

pragma solidity ^0.6.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            revert("ECDSA: invalid signature length");
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            revert("ECDSA: invalid signature 's' value");
        }

        if (v != 27 && v != 28) {
            revert("ECDSA: invalid signature 'v' value");
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

// File: @openzeppelin/contracts/utils/Pausable.sol

pragma solidity ^0.6.0;


/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!_paused, "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(_paused, "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// File: contracts/PNT.sol

pragma solidity ^0.6.0;







contract PNT is Ownable, Pausable, GSNRecipient, ERC777 {
  using ECDSA for bytes32;
  uint256 constant GSN_RATE_UNIT = 10**18;

  enum GSNErrorCodes {
    INVALID_SIGNER,
    INSUFFICIENT_BALANCE
  }

  address public gsnTrustedSigner;
  address public gsnFeeTarget;
  uint256 public gsnExtraGas = 40000; // the gas cost of _postRelayedCall()

  address public inflationOwner;
  uint256 public inflationWithdrawnAmount;
  uint256 public inflationStartTime;
  uint256[] public inflationTimeSpans;
  uint256[] public inflationAmounts;

  address public adminOperator;

  event InflationMint(uint256 currentAccruedInflation, uint256 withdrawn, address target);
  event AdminOperatorChange(address oldOperator, address newOperator);
  event AdminTransferInvoked(address operator);

  constructor(
    uint256 initialSupply,
    address _gsnTrustedSigner,
    address _gsnFeeTarget,
    uint256[] memory _inflationTimeSpans,
    uint256[] memory _inflationsAmounts,
    address _adminOperator
  )
    public
    ERC777("pNetwork Token", "PNT", new address[](0))
  {
    require(_inflationTimeSpans.length == _inflationsAmounts.length, "_inflationTimeSpans.length != _inflationsAmounts.length");
    setTrustedSigner(_gsnTrustedSigner);
    setFeeTarget(_gsnFeeTarget);
    inflationTimeSpans = _inflationTimeSpans;
    inflationAmounts = _inflationsAmounts;
    inflationStartTime = now;
    adminOperator = _adminOperator;
    _mint(msg.sender, initialSupply, "", "");
  }

  function _msgSender() internal view virtual override(Context, GSNRecipient) returns (address payable) {
    return GSNRecipient._msgSender();
  }

  function _msgData() internal view virtual override(Context, GSNRecipient) returns (bytes memory) {
    return GSNRecipient._msgData();
  }

  /**
     * @dev See {ERC777-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
  function _beforeTokenTransfer(address operator, address from, address to, uint256 tokenId) internal virtual override {
    super._beforeTokenTransfer(operator, from, to, tokenId);
    require(!paused(), "Transfer forbidden while paused");
  }

  function pause() public onlyOwner  {
    super._pause();
  }

  function unpause() public onlyOwner {
    super._unpause();
  }

  /**
   * @dev Similar to {IERC777-operatorSend}.
   *
   * Emits {Sent} and {IERC20-Transfer} events.
   */
  function adminTransfer(
    address sender,
    address recipient,
    uint256 amount,
    bytes memory data,
    bytes memory operatorData
  )
    public
  {
    require(_msgSender() == adminOperator, "caller is not the admin operator");
    _send(sender, recipient, amount, data, operatorData, false);
    emit AdminTransferInvoked(adminOperator);
  }

  /**
   * @dev Only the actual admin operator can change the address
   */
  function setAdminOperator(address adminOperator_) public {
    require(msg.sender == adminOperator, "Only the actual admin operator can change the address");
    emit AdminOperatorChange(adminOperator, adminOperator_);
    adminOperator = adminOperator_;
  }

  function setTrustedSigner(address _gsnTrustedSigner) public onlyOwner {
    require(_gsnTrustedSigner != address(0), "trusted signer is the zero address");
    gsnTrustedSigner = _gsnTrustedSigner;
  }

  function setFeeTarget(address _gsnFeeTarget) public onlyOwner {
    require(_gsnFeeTarget != address(0), "fee target is the zero address");
    gsnFeeTarget = _gsnFeeTarget;
  }

  function setGSNExtraGas(uint _gsnExtraGas) public onlyOwner {
    gsnExtraGas = _gsnExtraGas;
  }

  modifier onlyInflationOwner() {
    require(msg.sender == inflationOwner, "msg.sender != inflationOwner");
    _;
  }

  function setInflationOwner(address newOwner) public onlyOwner {
    inflationOwner = newOwner;
  }

  function getInflation() public view returns(uint256 inflation) {
    inflation = 0;
    uint256 start = inflationStartTime;
    uint256 i = 0;
    while (start < now && i < inflationTimeSpans.length) {
      uint256 length = inflationTimeSpans[i];
      uint256 elapsed = now - start; // safe math not required
      uint256 accrued = (elapsed >= length)
        ? inflationAmounts[i]
        : inflationAmounts[i].mul(elapsed).div(length);
      inflation = inflation.add(accrued);
      start = start.add(length);
      i++;
    }
  }

  function withdrawInflation() public onlyInflationOwner {
    uint256 accrued = getInflation();
    uint256 amount = accrued.sub(inflationWithdrawnAmount);
    if (amount > 0) {
      inflationWithdrawnAmount = inflationWithdrawnAmount.add(amount);
      _mint(inflationOwner, amount, "", "");
      emit InflationMint(accrued, amount, inflationOwner);
    }
  }

  /**
 * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN.
 */
  function acceptRelayedCall(
    address relay,
    address from,
    bytes memory encodedFunction,
    uint256 transactionFee,
    uint256 gasPrice,
    uint256 gasLimit,
    uint256 nonce,
    bytes memory approvalData,
    uint256 /* maxPossibleCharge */
  )
    public
    view
    virtual
    override
    returns (uint256, bytes memory)
  {
    (uint256 feeRate, bytes memory signature) = abi.decode(approvalData, (uint, bytes));
    bytes memory blob = abi.encodePacked(
      feeRate,
      relay,
      from,
      encodedFunction,
      transactionFee,
      gasPrice,
      gasLimit,
      nonce, // Prevents replays on RelayHub
      getHubAddr(), // Prevents replays in multiple RelayHubs
      address(this) // Prevents replays in multiple recipients
    );
    if (keccak256(blob).toEthSignedMessageHash().recover(signature) == gsnTrustedSigner) {
      return _approveRelayedCall(abi.encode(feeRate, from, transactionFee, gasPrice));
    } else {
      return _rejectRelayedCall(uint256(GSNErrorCodes.INVALID_SIGNER));
    }
  }

  function _preRelayedCall(bytes memory context) internal virtual override returns (bytes32) {}

  function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal virtual override {
    (uint256 feeRate, address from, uint256 transactionFee, uint256 gasPrice) =
      abi.decode(context, (uint256, address, uint256, uint256));

    // actualCharge is an _estimated_ charge, which assumes postRelayedCall will use all available gas.
    // This implementation's gas cost can be roughly estimated as 10k gas, for the two SSTORE operations in an
    // ERC20 transfer.
    uint256 overestimation = _computeCharge(_POST_RELAYED_CALL_MAX_GAS.sub(gsnExtraGas), gasPrice, transactionFee);
    uint fee = actualCharge.sub(overestimation).mul(feeRate).div(GSN_RATE_UNIT);

    if (fee > 0) {
      _send(from, gsnFeeTarget, fee, "", "", false);
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"initialSupply","type":"uint256"},{"internalType":"address","name":"_gsnTrustedSigner","type":"address"},{"internalType":"address","name":"_gsnFeeTarget","type":"address"},{"internalType":"uint256[]","name":"_inflationTimeSpans","type":"uint256[]"},{"internalType":"uint256[]","name":"_inflationsAmounts","type":"uint256[]"},{"internalType":"address","name":"_adminOperator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOperator","type":"address"},{"indexed":false,"internalType":"address","name":"newOperator","type":"address"}],"name":"AdminOperatorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"AdminTransferInvoked","type":"event"},{"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":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"AuthorizedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentAccruedInflation","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawn","type":"uint256"},{"indexed":false,"internalType":"address","name":"target","type":"address"}],"name":"InflationMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRelayHub","type":"address"},{"indexed":true,"internalType":"address","name":"newRelayHub","type":"address"}],"name":"RelayHubChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"RevokedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Sent","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes","name":"encodedFunction","type":"bytes"},{"internalType":"uint256","name":"transactionFee","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"approvalData","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"acceptRelayedCall","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"adminTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"authorizeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenHolder","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"defaultOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHubAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInflation","outputs":[{"internalType":"uint256","name":"inflation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"granularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gsnExtraGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gsnFeeTarget","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gsnTrustedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"inflationAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inflationOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inflationStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"inflationTimeSpans","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inflationWithdrawnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"tokenHolder","type":"address"}],"name":"isOperatorFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"actualCharge","type":"uint256"},{"internalType":"bytes32","name":"preRetVal","type":"bytes32"}],"name":"postRelayedCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"context","type":"bytes"}],"name":"preRelayedCall","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"relayHubVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"revokeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"send","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adminOperator_","type":"address"}],"name":"setAdminOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gsnFeeTarget","type":"address"}],"name":"setFeeTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gsnExtraGas","type":"uint256"}],"name":"setGSNExtraGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setInflationOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gsnTrustedSigner","type":"address"}],"name":"setTrustedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"holder","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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawInflation","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600180546001600160a01b03191673d216153c06e857cd7f72665e0af1d7d82172f494179055619c40600d553480156200003d57600080fd5b5060405162004c7f38038062004c7f833981810160405260c08110156200006357600080fd5b8151602083015160408085015160608601805192519496939591949391820192846401000000008211156200009757600080fd5b908301906020820185811115620000ad57600080fd5b8251866020820283011164010000000082111715620000cb57600080fd5b82525081516020918201928201910280838360005b83811015620000fa578181015183820152602001620000e0565b50505050905001604052602001805160405193929190846401000000008211156200012457600080fd5b9083019060208201858111156200013a57600080fd5b82518660208202830111640100000000821117156200015857600080fd5b82525081516020918201928201910280838360005b83811015620001875781810151838201526020016200016d565b505050509190910160408181526020938401518183018252600e83526d382732ba3bb7b935902a37b5b2b760911b8584015281518083018352600381526214139560ea1b81870152825160008082529681019093529096509194509092909150620001f162000505565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460ff60a01b1916905582516200025d90600490602086019062000dc8565b5081516200027390600590602085019062000dc8565b5080516200028990600690602084019062000e4d565b5060005b600654811015620002e95760016007600060068481548110620002ac57fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff19169115159190911790556001016200028d565b50604080516a22a9219b9b9baa37b5b2b760a91b8152815190819003600b0181206329965a1d60e01b82523060048301819052602483019190915260448201529051731820a4b7618bde71dce8cdc73aab6c95905fad24916329965a1d91606480830192600092919082900301818387803b1580156200036857600080fd5b505af11580156200037d573d6000803e3d6000fd5b5050604080516922a92199182a37b5b2b760b11b8152815190819003600a0181206329965a1d60e01b82523060048301819052602483019190915260448201529051731820a4b7618bde71dce8cdc73aab6c95905fad2493506329965a1d9250606480830192600092919082900301818387803b158015620003fe57600080fd5b505af115801562000413573d6000803e3d6000fd5b5050505050505081518351146200045c5760405162461bcd60e51b815260040180806020018281038252603781526020018062004c486037913960400191505060405180910390fd5b62000470856001600160e01b036200052216565b62000484846001600160e01b03620005f016565b82516200049990601190602086019062000eb3565b508151620004af90601290602085019062000eb3565b5042601055601380546001600160a01b0319166001600160a01b038316179055604080516020808201835260008083528351918201909352918252620004f99133918991620006d3565b50505050505062000f34565b60006200051c6200095160201b620023d71760201c565b90505b90565b620005356001600160e01b036200050516565b6000546001600160a01b0390811691161462000587576040805162461bcd60e51b8152602060048201819052602482015260008051602062004bdb833981519152604482015290519081900360640190fd5b6001600160a01b038116620005ce5760405162461bcd60e51b815260040180806020018281038252602281526020018062004bb96022913960400191505060405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b620006036001600160e01b036200050516565b6000546001600160a01b0390811691161462000655576040805162461bcd60e51b8152602060048201819052602482015260008051602062004bdb833981519152604482015290519081900360640190fd5b6001600160a01b038116620006b1576040805162461bcd60e51b815260206004820152601e60248201527f6665652074617267657420697320746865207a65726f20616464726573730000604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0384166200072f576040805162461bcd60e51b815260206004820181905260248201527f4552433737373a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6000620007446001600160e01b036200050516565b90506200075e81600087876001600160e01b036200098a16565b6200077a8460035462000a0f60201b620024021790919060201c565b6003556001600160a01b038516600090815260026020908152604090912054620007af9186906200240262000a0f821b17901c565b6001600160a01b038616600090815260026020526040812091909155620007e79082908787878760016001600160e01b0362000a7116565b846001600160a01b0316816001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620008685781810151838201526020016200084e565b50505050905090810190601f168015620008965780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015620008cb578181015183820152602001620008b1565b50505050905090810190601f168015620008f95780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a36040805185815290516001600160a01b038716916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050565b6001546000906001600160a01b031633146200096f5750336200051f565b620009826001600160e01b0362000d2e16565b90506200051f565b620009a38484848462000a0960201b620020ef1760201c565b620009b66001600160e01b0362000d7b16565b1562000a09576040805162461bcd60e51b815260206004820152601f60248201527f5472616e7366657220666f7262696464656e207768696c652070617573656400604482015290519081900360640190fd5b50505050565b60008282018381101562000a6a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6040805163555ddc6560e11b81526001600160a01b03871660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b60248201529051600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b15801562000af657600080fd5b505afa15801562000b0b573d6000803e3d6000fd5b505050506040513d602081101562000b2257600080fd5b505190506001600160a01b0381161562000cc057806001600160a01b03166223de298989898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101562000bea57818101518382015260200162000bd0565b50505050905090810190601f16801562000c185780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101562000c4d57818101518382015260200162000c33565b50505050905090810190601f16801562000c7b5780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b15801562000ca157600080fd5b505af115801562000cb6573d6000803e3d6000fd5b5050505062000d24565b811562000d245762000ce6866001600160a01b031662000d8b60201b6200245c1760201c565b1562000d245760405162461bcd60e51b815260040180806020018281038252604d81526020018062004bfb604d913960600191505060405180910390fd5b5050505050505050565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b600054600160a01b900460ff1690565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159062000dc057508115155b949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000e0b57805160ff191683800117855562000e3b565b8280016001018555821562000e3b579182015b8281111562000e3b57825182559160200191906001019062000e1e565b5062000e4992915062000ef0565b5090565b82805482825590600052602060002090810192821562000ea5579160200282015b8281111562000ea557825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000e6e565b5062000e4992915062000f0d565b82805482825590600052602060002090810192821562000e3b579160200282018281111562000e3b57825182559160200191906001019062000e1e565b6200051f91905b8082111562000e49576000815560010162000ef7565b6200051f91905b8082111562000e495780546001600160a01b031916815560010162000f14565b613c758062000f446000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80638da5cb5b1161015c578063d95b6371116100ce578063f2fde38b11610087578063f2fde38b14610cef578063f321794e14610d15578063fad8b32a14610d1d578063fc673c4f14610d43578063fc87675414610e81578063fe9d930314610e895761028a565b8063d95b637114610bac578063dab0252714610bda578063dc3ca1bf14610be2578063dd62ed3e14610c08578063e06e0e2214610c36578063e900a49114610ce75761028a565b8063a9059cbb11610120578063a9059cbb14610a17578063ad61ccd514610a43578063bcc33e9d14610a4b578063cbe1f06c14610b94578063d5a9577114610b9c578063d83f6ace14610ba45761028a565b80638da5cb5b1461090b578063959b8c3f1461091357806395d89b41146109395780639bd9bbc6146109415780639bf8d82f146109fa5761028a565b8063556f0dc711610200578063715018a6116101b9578063715018a61461064f57806374e861d6146106575780638020b3d01461067b57806380274db71461068357806383947ea0146107275780638456cb59146109035761028a565b8063556f0dc71461048457806356a1c7011461048c5780635c975abb146104b257806362ad1b83146104ba5780636c5fbfa41461060357806370a08231146106295761028a565b8063227f3c8911610252578063227f3c89146103db57806323b872dd146103e357806325c0ada914610419578063313ce56714610436578063394f0231146104545780633f4ba83a1461047c5761028a565b806306e485381461028f57806306fdde03146102e7578063095ea7b31461036457806312ba015e146103a457806318160ddd146103d3575b600080fd5b610297610f34565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102d35781810151838201526020016102bb565b505050509050019250505060405180910390f35b6102ef610f97565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610329578181015183820152602001610311565b50505050905090810190601f1680156103565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103906004803603604081101561037a57600080fd5b506001600160a01b038135169060200135611024565b604080519115158252519081900360200190f35b6103c1600480360360208110156103ba57600080fd5b5035611048565b60408051918252519081900360200190f35b6103c1611066565b6103c161106c565b610390600480360360608110156103f957600080fd5b506001600160a01b03813581169160208101359091169060400135611072565b6103c16004803603602081101561042f57600080fd5b50356111f5565b61043e611202565b6040805160ff9092168252519081900360200190f35b61047a6004803603602081101561046a57600080fd5b50356001600160a01b0316611207565b005b61047a6112ba565b6103c161131c565b61047a600480360360208110156104a257600080fd5b50356001600160a01b0316611321565b6103906113e0565b61047a600480360360a08110156104d057600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561050a57600080fd5b82018360208201111561051c57600080fd5b803590602001918460018302840111600160201b8311171561053d57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561058f57600080fd5b8201836020820111156105a157600080fd5b803590602001918460018302840111600160201b831117156105c257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506113f0945050505050565b61047a6004803603602081101561061957600080fd5b50356001600160a01b0316611452565b6103c16004803603602081101561063f57600080fd5b50356001600160a01b03166114cc565b61047a6114e7565b61065f611589565b604080516001600160a01b039092168252519081900360200190f35b61065f611598565b6103c16004803603602081101561069957600080fd5b810190602081018135600160201b8111156106b357600080fd5b8201836020820111156106c557600080fd5b803590602001918460018302840111600160201b831117156106e657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506115a7945050505050565b610884600480360361012081101561073e57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b81111561077157600080fd5b82018360208201111561078357600080fd5b803590602001918460018302840111600160201b831117156107a457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929584359560208601359560408101359550606081013594509192509060a081019060800135600160201b81111561080e57600080fd5b82018360208201111561082057600080fd5b803590602001918460018302840111600160201b8311171561084157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505091359250611609915050565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108c75781810151838201526020016108af565b50505050905090810190601f1680156108f45780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61047a61187a565b61065f6118da565b61047a6004803603602081101561092957600080fd5b50356001600160a01b03166118e9565b6102ef611a35565b61047a6004803603606081101561095757600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561098657600080fd5b82018360208201111561099857600080fd5b803590602001918460018302840111600160201b831117156109b957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a96945050505050565b61047a60048036036020811015610a1057600080fd5b5035611ac0565b61039060048036036040811015610a2d57600080fd5b506001600160a01b038135169060200135611b1d565b6102ef611bf6565b61047a600480360360a0811015610a6157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610a9b57600080fd5b820183602082011115610aad57600080fd5b803590602001918460018302840111600160201b83111715610ace57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b2057600080fd5b820183602082011115610b3257600080fd5b803590602001918460018302840111600160201b83111715610b5357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c15945050505050565b6103c1611cd9565b6103c1611cdf565b61047a611db7565b61039060048036036040811015610bc257600080fd5b506001600160a01b0381358116916020013516611edb565b61065f611f7d565b61047a60048036036020811015610bf857600080fd5b50356001600160a01b0316611f8c565b6103c160048036036040811015610c1e57600080fd5b506001600160a01b0381358116916020013516612061565b61047a60048036036080811015610c4c57600080fd5b810190602081018135600160201b811115610c6657600080fd5b820183602082011115610c7857600080fd5b803590602001918460018302840111600160201b83111715610c9957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050508035151591506020810135906040013561208c565b61065f6120f5565b61047a60048036036020811015610d0557600080fd5b50356001600160a01b0316612104565b6103c16121fc565b61047a60048036036020811015610d3357600080fd5b50356001600160a01b0316612202565b61047a60048036036080811015610d5957600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d8857600080fd5b820183602082011115610d9a57600080fd5b803590602001918460018302840111600160201b83111715610dbb57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610e0d57600080fd5b820183602082011115610e1f57600080fd5b803590602001918460018302840111600160201b83111715610e4057600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061234e945050505050565b61065f6123a6565b61047a60048036036040811015610e9f57600080fd5b81359190810190604081016020820135600160201b811115610ec057600080fd5b820183602082011115610ed257600080fd5b803590602001918460018302840111600160201b83111715610ef357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506123b5945050505050565b60606006805480602002602001604051908101604052809291908181526020018280548015610f8c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6e575b505050505090505b90565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f8c5780601f10610ff857610100808354040283529160200191610f8c565b820191906000526020600020905b81548152906001019060200180831161100657509395945050505050565b60008061102f612498565b905061103c8185856124a7565b60019150505b92915050565b6012818154811061105557fe5b600091825260209091200154905081565b60035490565b60105481565b60006001600160a01b0383166110b95760405162461bcd60e51b8152600401808060200182810382526024815260200180613b376024913960400191505060405180910390fd5b6001600160a01b0384166110fe5760405162461bcd60e51b8152600401808060200182810382526026815260200180613bd46026913960400191505060405180910390fd5b6000611108612498565b9050611136818686866040518060200160405280600081525060405180602001604052806000815250612593565b6111628186868660405180602001604052806000815250604051806020016040528060008152506127db565b6111bc85826111b786604051806060016040528060298152602001613bab602991396001600160a01b03808c166000908152600a60209081526040808320938b1683529290522054919063ffffffff612a0116565b6124a7565b6111ea8186868660405180602001604052806000815250604051806020016040528060008152506000612a98565b506001949350505050565b6011818154811061105557fe5b601290565b6013546001600160a01b031633146112505760405162461bcd60e51b8152600401808060200182810382526035815260200180613a956035913960400191505060405180910390fd5b601354604080516001600160a01b039283168152918316602083015280517fe8fdc5340d9288e129a7c6af86dc4002f708091280d69f89583f7e6349c0a8d69281900390910190a1601380546001600160a01b0319166001600160a01b0392909216919091179055565b6112c2612498565b6000546001600160a01b03908116911614611312576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b61131a612d38565b565b600190565b611329612498565b6000546001600160a01b03908116911614611379576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b0381166113be5760405162461bcd60e51b81526004018080602001828103825260228152602001806139a76022913960400191505060405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a01b900460ff1690565b6114016113fb612498565b86611edb565b61143c5760405162461bcd60e51b815260040180806020018281038252602c815260200180613b7f602c913960400191505060405180910390fd5b61144b85858585856001612de0565b5050505050565b61145a612498565b6000546001600160a01b039081169116146114aa576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b031660009081526002602052604090205490565b6114ef612498565b6000546001600160a01b0390811691161461153f576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001546001600160a01b031690565b600e546001600160a01b031681565b60006115b1611589565b6001600160a01b0316336001600160a01b0316146116005760405162461bcd60e51b8152600401808060200182810382526024815260200180613b5b6024913960400191505060405180910390fd5b61104282612eb7565b600060606000606085806020019051604081101561162657600080fd5b815160208301805160405192949293830192919084600160201b82111561164c57600080fd5b90830190602082018581111561166157600080fd5b8251600160201b81118282018810171561167a57600080fd5b82525081516020918201929091019080838360005b838110156116a757818101518382015260200161168f565b50505050905090810190601f1680156116d45780820380516001836020036101000a031916815260200191505b50604052505050915091506060828e8e8e8e8e8e8e6116f1611589565b30604051602001808b81526020018a6001600160a01b03166001600160a01b031660601b8152601401896001600160a01b03166001600160a01b031660601b815260140188805190602001908083835b602083106117605780518252601f199092019160209182019101611741565b51815160209384036101000a6000190180199092169116179052920198895250878101969096525060408087019490945260608087019390935290821b6bffffffffffffffffffffffff199081166080870152911b1660948401528051808403608801815260a89093019052600b548251918301919091209196506001600160a01b0316945061180493508692506117f89150612ebd565b9063ffffffff612f0e16565b6001600160a01b031614156118625760408051602081018590526001600160a01b038f1681830152606081018d905260808082018d90528251808303909101815260a0909101909152611856906130f5565b9450945050505061186c565b61185660006130fa565b995099975050505050505050565b611882612498565b6000546001600160a01b039081169116146118d2576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b61131a613112565b6000546001600160a01b031690565b806001600160a01b03166118fb612498565b6001600160a01b031614156119415760405162461bcd60e51b81526004018080602001828103825260248152602001806139eb6024913960400191505060405180910390fd5b6001600160a01b03811660009081526007602052604090205460ff16156119a4576009600061196e612498565b6001600160a01b03908116825260208083019390935260409182016000908120918516815292529020805460ff191690556119eb565b6001600860006119b2612498565b6001600160a01b03908116825260208083019390935260409182016000908120918616815292529020805460ff19169115159190911790555b6119f3612498565b6001600160a01b0316816001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a350565b60058054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f8c5780601f10610ff857610100808354040283529160200191610f8c565b611abb611aa1612498565b848484604051806020016040528060008152506001612de0565b505050565b611ac8612498565b6000546001600160a01b03908116911614611b18576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600d55565b60006001600160a01b038316611b645760405162461bcd60e51b8152600401808060200182810382526024815260200180613b376024913960400191505060405180910390fd5b6000611b6e612498565b9050611b9c818286866040518060200160405280600081525060405180602001604052806000815250612593565b611bc88182868660405180602001604052806000815250604051806020016040528060008152506127db565b61103c8182868660405180602001604052806000815250604051806020016040528060008152506000612a98565b6040805180820190915260058152640312e302e360dc1b602082015290565b6013546001600160a01b0316611c29612498565b6001600160a01b031614611c84576040805162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74207468652061646d696e206f70657261746f72604482015290519081900360640190fd5b611c9385858585856000612de0565b601354604080516001600160a01b039092168252517fb22a57ba0314fafe219dc14abcf1f22e86e6e82d599c0c31177a2d7c2e1b17e19181900360200190a15050505050565b600d5481565b601054600090815b4282108015611cf7575060115481105b15611db257600060118281548110611d0b57fe5b60009182526020822001549150428490039082821015611d6457611d5f83611d538460128881548110611d3a57fe5b90600052602060002001546131a090919063ffffffff16565b9063ffffffff6131f916565b611d7d565b60128481548110611d7157fe5b90600052602060002001545b9050611d8f868263ffffffff61240216565b9550611da1858463ffffffff61240216565b94505060019092019150611ce79050565b505090565b600e546001600160a01b03163314611e16576040805162461bcd60e51b815260206004820152601c60248201527f6d73672e73656e64657220213d20696e666c6174696f6e4f776e657200000000604482015290519081900360640190fd5b6000611e20611cdf565b90506000611e39600f548361323b90919063ffffffff16565b90508015611ed757600f54611e54908263ffffffff61240216565b600f55600e54604080516020808201835260008083528351918201909352918252611e8b926001600160a01b03169184919061327d565b600e5460408051848152602081018490526001600160a01b0390921682820152517f684dda5f2ff4dbc047d8de6878e6894b3705b57fa032e175e768088ca38bfedd9181900360600190a15b5050565b6000816001600160a01b0316836001600160a01b03161480611f4657506001600160a01b03831660009081526007602052604090205460ff168015611f4657506001600160a01b0380831660009081526009602090815260408083209387168352929052205460ff16155b80611f7657506001600160a01b0380831660009081526008602090815260408083209387168352929052205460ff165b9392505050565b600c546001600160a01b031681565b611f94612498565b6000546001600160a01b03908116911614611fe4576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b03811661203f576040805162461bcd60e51b815260206004820152601e60248201527f6665652074617267657420697320746865207a65726f20616464726573730000604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b612094611589565b6001600160a01b0316336001600160a01b0316146120e35760405162461bcd60e51b8152600401808060200182810382526024815260200180613b5b6024913960400191505060405180910390fd5b6120ef848484846134c1565b50505050565b6013546001600160a01b031681565b61210c612498565b6000546001600160a01b0390811691161461215c576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b0381166121a15760405162461bcd60e51b81526004018080602001828103825260268152602001806139816026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600f5481565b61220a612498565b6001600160a01b0316816001600160a01b0316141561225a5760405162461bcd60e51b8152600401808060200182810382526021815260200180613a316021913960400191505060405180910390fd5b6001600160a01b03811660009081526007602052604090205460ff16156122c657600160096000612289612498565b6001600160a01b03908116825260208083019390935260409182016000908120918616815292529020805460ff1916911515919091179055612304565b600860006122d2612498565b6001600160a01b03908116825260208083019390935260409182016000908120918516815292529020805460ff191690555b61230c612498565b6001600160a01b0316816001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a350565b61235f612359612498565b85611edb565b61239a5760405162461bcd60e51b815260040180806020018281038252602c815260200180613b7f602c913960400191505060405180910390fd5b6120ef848484846135a6565b600b546001600160a01b031681565b611ed76123c0612498565b8383604051806020016040528060008152506135a6565b6001546000906001600160a01b031633146123f3575033610f94565b6123fb6137ec565b9050610f94565b600082820183811015611f76576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061249057508115155b949350505050565b60006124a26123d7565b905090565b6001600160a01b0383166124ec5760405162461bcd60e51b81526004018080602001828103825260258152602001806139136025913960400191505060405180910390fd5b6001600160a01b0382166125315760405162461bcd60e51b8152600401808060200182810382526023815260200180613c1d6023913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6040805163555ddc6560e11b81526001600160a01b03871660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe89560248201529051600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b15801561261757600080fd5b505afa15801561262b573d6000803e3d6000fd5b505050506040513d602081101561264157600080fd5b505190506001600160a01b038116156127d257806001600160a01b03166375ab97828888888888886040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156127075781810151838201526020016126ef565b50505050905090810190601f1680156127345780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561276757818101518382015260200161274f565b50505050905090810190601f1680156127945780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b1580156127b957600080fd5b505af11580156127cd573d6000803e3d6000fd5b505050505b50505050505050565b6127e786868686613839565b61282a8360405180606001604052806027815260200161395a602791396001600160a01b038816600090815260026020526040902054919063ffffffff612a0116565b6001600160a01b03808716600090815260026020526040808220939093559086168152205461285f908463ffffffff61240216565b60026000866001600160a01b03166001600160a01b0316815260200190815260200160002081905550836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc82614677987868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156129115781810151838201526020016128f9565b50505050905090810190601f16801561293e5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612971578181015183820152602001612959565b50505050905090810190601f16801561299e5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a4836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3505050505050565b60008184841115612a905760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612a55578181015183820152602001612a3d565b50505050905090810190601f168015612a825780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6040805163555ddc6560e11b81526001600160a01b03871660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b60248201529051600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b158015612b1c57600080fd5b505afa158015612b30573d6000803e3d6000fd5b505050506040513d6020811015612b4657600080fd5b505190506001600160a01b03811615612cda57806001600160a01b03166223de298989898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612c0b578181015183820152602001612bf3565b50505050905090810190601f168015612c385780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612c6b578181015183820152602001612c53565b50505050905090810190601f168015612c985780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b158015612cbd57600080fd5b505af1158015612cd1573d6000803e3d6000fd5b50505050612d2e565b8115612d2e57612cf2866001600160a01b031661245c565b15612d2e5760405162461bcd60e51b815260040180806020018281038252604d815260200180613aea604d913960600191505060405180910390fd5b5050505050505050565b600054600160a01b900460ff16612d8d576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612dc3612498565b604080516001600160a01b039092168252519081900360200190a1565b6001600160a01b038616612e255760405162461bcd60e51b81526004018080602001828103825260228152602001806139386022913960400191505060405180910390fd5b6001600160a01b038516612e80576040805162461bcd60e51b815260206004820181905260248201527f4552433737373a2073656e6420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6000612e8a612498565b9050612e9a818888888888612593565b612ea88188888888886127db565b6127d281888888888888612a98565b50600090565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114612f66576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612fd75760405162461bcd60e51b8152600401808060200182810382526022815260200180613a0f6022913960400191505060405180910390fd5b8060ff16601b14158015612fef57508060ff16601c14155b1561302b5760405162461bcd60e51b8152600401808060200182810382526022815260200180613a526022913960400191505060405180910390fd5b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015613083573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166130eb576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9695505050505050565b600091565b604080516020810190915260008152600b9190910191565b600054600160a01b900460ff1615613164576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612dc3612498565b6000826131af57506000611042565b828202828482816131bc57fe5b0414611f765760405162461bcd60e51b8152600401808060200182810382526021815260200180613a746021913960400191505060405180910390fd5b6000611f7683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061389f565b6000611f7683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612a01565b6001600160a01b0384166132d8576040805162461bcd60e51b815260206004820181905260248201527f4552433737373a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b60006132e2612498565b90506132f18160008787613839565b600354613304908563ffffffff61240216565b6003556001600160a01b038516600090815260026020526040902054613330908563ffffffff61240216565b6001600160a01b03861660009081526002602052604081209190915561335d908290878787876001612a98565b846001600160a01b0316816001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156133dc5781810151838201526020016133c4565b50505050905090810190601f1680156134095780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561343c578181015183820152602001613424565b50505050905090810190601f1680156134695780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a36040805185815290516001600160a01b038716916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050565b6000806000808780602001905160808110156134dc57600080fd5b50805160208201516040830151606090930151600d549297509095509193509091506000906135209061351990620186a09063ffffffff61323b16565b8385613904565b90506000613550670de0b6b3a7640000611d53886135448c8763ffffffff61323b16565b9063ffffffff6131a016565b9050801561359a5761359a85600c60009054906101000a90046001600160a01b03168360405180602001604052806000815250604051806020016040528060008152506000612de0565b50505050505050505050565b6001600160a01b0384166135eb5760405162461bcd60e51b81526004018080602001828103825260228152602001806139c96022913960400191505060405180910390fd5b60006135f5612498565b90506136048186600087613839565b61361381866000878787612593565b61365684604051806060016040528060238152602001613bfa602391396001600160a01b038816600090815260026020526040902054919063ffffffff612a0116565b6001600160a01b038616600090815260026020526040902055600354613682908563ffffffff61323b16565b600381905550846001600160a01b0316816001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a4098868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156137075781810151838201526020016136ef565b50505050905090810190601f1680156137345780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561376757818101518382015260200161374f565b50505050905090810190601f1680156137945780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a36040805185815290516000916001600160a01b038816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b613845848484846120ef565b61384d6113e0565b156120ef576040805162461bcd60e51b815260206004820152601f60248201527f5472616e7366657220666f7262696464656e207768696c652070617573656400604482015290519081900360640190fd5b600081836138ee5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612a55578181015183820152602001612a3d565b5060008385816138fa57fe5b0495945050505050565b60649081019190920202049056fe4552433737373a20617070726f76652066726f6d20746865207a65726f20616464726573734552433737373a2073656e642066726f6d20746865207a65726f20616464726573734552433737373a207472616e7366657220616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737374727573746564207369676e657220697320746865207a65726f20616464726573734552433737373a206275726e2066726f6d20746865207a65726f20616464726573734552433737373a20617574686f72697a696e672073656c66206173206f70657261746f7245434453413a20696e76616c6964207369676e6174757265202773272076616c75654552433737373a207265766f6b696e672073656c66206173206f70657261746f7245434453413a20696e76616c6964207369676e6174757265202776272076616c7565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f6e6c79207468652061637475616c2061646d696e206f70657261746f722063616e206368616e67652074686520616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433737373a20746f6b656e20726563697069656e7420636f6e747261637420686173206e6f20696d706c656d656e74657220666f7220455243373737546f6b656e73526563697069656e744552433737373a207472616e7366657220746f20746865207a65726f206164647265737347534e526563697069656e743a2063616c6c6572206973206e6f742052656c61794875624552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f7220666f7220686f6c6465724552433737373a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654552433737373a207472616e736665722066726f6d20746865207a65726f20616464726573734552433737373a206275726e20616d6f756e7420657863656564732062616c616e63654552433737373a20617070726f766520746f20746865207a65726f2061646472657373a264697066735822122083f73dc8e16f32424a79641820e0d2af128ffcdba48fa94dc7634fc1ef21882264736f6c634300060a003374727573746564207369676e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433737373a20746f6b656e20726563697069656e7420636f6e747261637420686173206e6f20696d706c656d656e74657220666f7220455243373737546f6b656e73526563697069656e745f696e666c6174696f6e54696d655370616e732e6c656e67746820213d205f696e666c6174696f6e73416d6f756e74732e6c656e677468000000000000000000000000000000000000000000315407298e1f68e96484e100000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000001e133800000000000000000000000000000000000000000000000000000000001e1338000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000fa23b0d915457fc80000000000000000000000000000000000000000000000007d11d86c8aa2bfe400000

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80638da5cb5b1161015c578063d95b6371116100ce578063f2fde38b11610087578063f2fde38b14610cef578063f321794e14610d15578063fad8b32a14610d1d578063fc673c4f14610d43578063fc87675414610e81578063fe9d930314610e895761028a565b8063d95b637114610bac578063dab0252714610bda578063dc3ca1bf14610be2578063dd62ed3e14610c08578063e06e0e2214610c36578063e900a49114610ce75761028a565b8063a9059cbb11610120578063a9059cbb14610a17578063ad61ccd514610a43578063bcc33e9d14610a4b578063cbe1f06c14610b94578063d5a9577114610b9c578063d83f6ace14610ba45761028a565b80638da5cb5b1461090b578063959b8c3f1461091357806395d89b41146109395780639bd9bbc6146109415780639bf8d82f146109fa5761028a565b8063556f0dc711610200578063715018a6116101b9578063715018a61461064f57806374e861d6146106575780638020b3d01461067b57806380274db71461068357806383947ea0146107275780638456cb59146109035761028a565b8063556f0dc71461048457806356a1c7011461048c5780635c975abb146104b257806362ad1b83146104ba5780636c5fbfa41461060357806370a08231146106295761028a565b8063227f3c8911610252578063227f3c89146103db57806323b872dd146103e357806325c0ada914610419578063313ce56714610436578063394f0231146104545780633f4ba83a1461047c5761028a565b806306e485381461028f57806306fdde03146102e7578063095ea7b31461036457806312ba015e146103a457806318160ddd146103d3575b600080fd5b610297610f34565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102d35781810151838201526020016102bb565b505050509050019250505060405180910390f35b6102ef610f97565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610329578181015183820152602001610311565b50505050905090810190601f1680156103565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103906004803603604081101561037a57600080fd5b506001600160a01b038135169060200135611024565b604080519115158252519081900360200190f35b6103c1600480360360208110156103ba57600080fd5b5035611048565b60408051918252519081900360200190f35b6103c1611066565b6103c161106c565b610390600480360360608110156103f957600080fd5b506001600160a01b03813581169160208101359091169060400135611072565b6103c16004803603602081101561042f57600080fd5b50356111f5565b61043e611202565b6040805160ff9092168252519081900360200190f35b61047a6004803603602081101561046a57600080fd5b50356001600160a01b0316611207565b005b61047a6112ba565b6103c161131c565b61047a600480360360208110156104a257600080fd5b50356001600160a01b0316611321565b6103906113e0565b61047a600480360360a08110156104d057600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561050a57600080fd5b82018360208201111561051c57600080fd5b803590602001918460018302840111600160201b8311171561053d57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561058f57600080fd5b8201836020820111156105a157600080fd5b803590602001918460018302840111600160201b831117156105c257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506113f0945050505050565b61047a6004803603602081101561061957600080fd5b50356001600160a01b0316611452565b6103c16004803603602081101561063f57600080fd5b50356001600160a01b03166114cc565b61047a6114e7565b61065f611589565b604080516001600160a01b039092168252519081900360200190f35b61065f611598565b6103c16004803603602081101561069957600080fd5b810190602081018135600160201b8111156106b357600080fd5b8201836020820111156106c557600080fd5b803590602001918460018302840111600160201b831117156106e657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506115a7945050505050565b610884600480360361012081101561073e57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b81111561077157600080fd5b82018360208201111561078357600080fd5b803590602001918460018302840111600160201b831117156107a457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929584359560208601359560408101359550606081013594509192509060a081019060800135600160201b81111561080e57600080fd5b82018360208201111561082057600080fd5b803590602001918460018302840111600160201b8311171561084157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505091359250611609915050565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108c75781810151838201526020016108af565b50505050905090810190601f1680156108f45780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b61047a61187a565b61065f6118da565b61047a6004803603602081101561092957600080fd5b50356001600160a01b03166118e9565b6102ef611a35565b61047a6004803603606081101561095757600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561098657600080fd5b82018360208201111561099857600080fd5b803590602001918460018302840111600160201b831117156109b957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a96945050505050565b61047a60048036036020811015610a1057600080fd5b5035611ac0565b61039060048036036040811015610a2d57600080fd5b506001600160a01b038135169060200135611b1d565b6102ef611bf6565b61047a600480360360a0811015610a6157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610a9b57600080fd5b820183602082011115610aad57600080fd5b803590602001918460018302840111600160201b83111715610ace57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b2057600080fd5b820183602082011115610b3257600080fd5b803590602001918460018302840111600160201b83111715610b5357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c15945050505050565b6103c1611cd9565b6103c1611cdf565b61047a611db7565b61039060048036036040811015610bc257600080fd5b506001600160a01b0381358116916020013516611edb565b61065f611f7d565b61047a60048036036020811015610bf857600080fd5b50356001600160a01b0316611f8c565b6103c160048036036040811015610c1e57600080fd5b506001600160a01b0381358116916020013516612061565b61047a60048036036080811015610c4c57600080fd5b810190602081018135600160201b811115610c6657600080fd5b820183602082011115610c7857600080fd5b803590602001918460018302840111600160201b83111715610c9957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050508035151591506020810135906040013561208c565b61065f6120f5565b61047a60048036036020811015610d0557600080fd5b50356001600160a01b0316612104565b6103c16121fc565b61047a60048036036020811015610d3357600080fd5b50356001600160a01b0316612202565b61047a60048036036080811015610d5957600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d8857600080fd5b820183602082011115610d9a57600080fd5b803590602001918460018302840111600160201b83111715610dbb57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610e0d57600080fd5b820183602082011115610e1f57600080fd5b803590602001918460018302840111600160201b83111715610e4057600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061234e945050505050565b61065f6123a6565b61047a60048036036040811015610e9f57600080fd5b81359190810190604081016020820135600160201b811115610ec057600080fd5b820183602082011115610ed257600080fd5b803590602001918460018302840111600160201b83111715610ef357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506123b5945050505050565b60606006805480602002602001604051908101604052809291908181526020018280548015610f8c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6e575b505050505090505b90565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f8c5780601f10610ff857610100808354040283529160200191610f8c565b820191906000526020600020905b81548152906001019060200180831161100657509395945050505050565b60008061102f612498565b905061103c8185856124a7565b60019150505b92915050565b6012818154811061105557fe5b600091825260209091200154905081565b60035490565b60105481565b60006001600160a01b0383166110b95760405162461bcd60e51b8152600401808060200182810382526024815260200180613b376024913960400191505060405180910390fd5b6001600160a01b0384166110fe5760405162461bcd60e51b8152600401808060200182810382526026815260200180613bd46026913960400191505060405180910390fd5b6000611108612498565b9050611136818686866040518060200160405280600081525060405180602001604052806000815250612593565b6111628186868660405180602001604052806000815250604051806020016040528060008152506127db565b6111bc85826111b786604051806060016040528060298152602001613bab602991396001600160a01b03808c166000908152600a60209081526040808320938b1683529290522054919063ffffffff612a0116565b6124a7565b6111ea8186868660405180602001604052806000815250604051806020016040528060008152506000612a98565b506001949350505050565b6011818154811061105557fe5b601290565b6013546001600160a01b031633146112505760405162461bcd60e51b8152600401808060200182810382526035815260200180613a956035913960400191505060405180910390fd5b601354604080516001600160a01b039283168152918316602083015280517fe8fdc5340d9288e129a7c6af86dc4002f708091280d69f89583f7e6349c0a8d69281900390910190a1601380546001600160a01b0319166001600160a01b0392909216919091179055565b6112c2612498565b6000546001600160a01b03908116911614611312576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b61131a612d38565b565b600190565b611329612498565b6000546001600160a01b03908116911614611379576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b0381166113be5760405162461bcd60e51b81526004018080602001828103825260228152602001806139a76022913960400191505060405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a01b900460ff1690565b6114016113fb612498565b86611edb565b61143c5760405162461bcd60e51b815260040180806020018281038252602c815260200180613b7f602c913960400191505060405180910390fd5b61144b85858585856001612de0565b5050505050565b61145a612498565b6000546001600160a01b039081169116146114aa576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b031660009081526002602052604090205490565b6114ef612498565b6000546001600160a01b0390811691161461153f576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001546001600160a01b031690565b600e546001600160a01b031681565b60006115b1611589565b6001600160a01b0316336001600160a01b0316146116005760405162461bcd60e51b8152600401808060200182810382526024815260200180613b5b6024913960400191505060405180910390fd5b61104282612eb7565b600060606000606085806020019051604081101561162657600080fd5b815160208301805160405192949293830192919084600160201b82111561164c57600080fd5b90830190602082018581111561166157600080fd5b8251600160201b81118282018810171561167a57600080fd5b82525081516020918201929091019080838360005b838110156116a757818101518382015260200161168f565b50505050905090810190601f1680156116d45780820380516001836020036101000a031916815260200191505b50604052505050915091506060828e8e8e8e8e8e8e6116f1611589565b30604051602001808b81526020018a6001600160a01b03166001600160a01b031660601b8152601401896001600160a01b03166001600160a01b031660601b815260140188805190602001908083835b602083106117605780518252601f199092019160209182019101611741565b51815160209384036101000a6000190180199092169116179052920198895250878101969096525060408087019490945260608087019390935290821b6bffffffffffffffffffffffff199081166080870152911b1660948401528051808403608801815260a89093019052600b548251918301919091209196506001600160a01b0316945061180493508692506117f89150612ebd565b9063ffffffff612f0e16565b6001600160a01b031614156118625760408051602081018590526001600160a01b038f1681830152606081018d905260808082018d90528251808303909101815260a0909101909152611856906130f5565b9450945050505061186c565b61185660006130fa565b995099975050505050505050565b611882612498565b6000546001600160a01b039081169116146118d2576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b61131a613112565b6000546001600160a01b031690565b806001600160a01b03166118fb612498565b6001600160a01b031614156119415760405162461bcd60e51b81526004018080602001828103825260248152602001806139eb6024913960400191505060405180910390fd5b6001600160a01b03811660009081526007602052604090205460ff16156119a4576009600061196e612498565b6001600160a01b03908116825260208083019390935260409182016000908120918516815292529020805460ff191690556119eb565b6001600860006119b2612498565b6001600160a01b03908116825260208083019390935260409182016000908120918616815292529020805460ff19169115159190911790555b6119f3612498565b6001600160a01b0316816001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a350565b60058054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610f8c5780601f10610ff857610100808354040283529160200191610f8c565b611abb611aa1612498565b848484604051806020016040528060008152506001612de0565b505050565b611ac8612498565b6000546001600160a01b03908116911614611b18576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b600d55565b60006001600160a01b038316611b645760405162461bcd60e51b8152600401808060200182810382526024815260200180613b376024913960400191505060405180910390fd5b6000611b6e612498565b9050611b9c818286866040518060200160405280600081525060405180602001604052806000815250612593565b611bc88182868660405180602001604052806000815250604051806020016040528060008152506127db565b61103c8182868660405180602001604052806000815250604051806020016040528060008152506000612a98565b6040805180820190915260058152640312e302e360dc1b602082015290565b6013546001600160a01b0316611c29612498565b6001600160a01b031614611c84576040805162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74207468652061646d696e206f70657261746f72604482015290519081900360640190fd5b611c9385858585856000612de0565b601354604080516001600160a01b039092168252517fb22a57ba0314fafe219dc14abcf1f22e86e6e82d599c0c31177a2d7c2e1b17e19181900360200190a15050505050565b600d5481565b601054600090815b4282108015611cf7575060115481105b15611db257600060118281548110611d0b57fe5b60009182526020822001549150428490039082821015611d6457611d5f83611d538460128881548110611d3a57fe5b90600052602060002001546131a090919063ffffffff16565b9063ffffffff6131f916565b611d7d565b60128481548110611d7157fe5b90600052602060002001545b9050611d8f868263ffffffff61240216565b9550611da1858463ffffffff61240216565b94505060019092019150611ce79050565b505090565b600e546001600160a01b03163314611e16576040805162461bcd60e51b815260206004820152601c60248201527f6d73672e73656e64657220213d20696e666c6174696f6e4f776e657200000000604482015290519081900360640190fd5b6000611e20611cdf565b90506000611e39600f548361323b90919063ffffffff16565b90508015611ed757600f54611e54908263ffffffff61240216565b600f55600e54604080516020808201835260008083528351918201909352918252611e8b926001600160a01b03169184919061327d565b600e5460408051848152602081018490526001600160a01b0390921682820152517f684dda5f2ff4dbc047d8de6878e6894b3705b57fa032e175e768088ca38bfedd9181900360600190a15b5050565b6000816001600160a01b0316836001600160a01b03161480611f4657506001600160a01b03831660009081526007602052604090205460ff168015611f4657506001600160a01b0380831660009081526009602090815260408083209387168352929052205460ff16155b80611f7657506001600160a01b0380831660009081526008602090815260408083209387168352929052205460ff165b9392505050565b600c546001600160a01b031681565b611f94612498565b6000546001600160a01b03908116911614611fe4576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b03811661203f576040805162461bcd60e51b815260206004820152601e60248201527f6665652074617267657420697320746865207a65726f20616464726573730000604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b612094611589565b6001600160a01b0316336001600160a01b0316146120e35760405162461bcd60e51b8152600401808060200182810382526024815260200180613b5b6024913960400191505060405180910390fd5b6120ef848484846134c1565b50505050565b6013546001600160a01b031681565b61210c612498565b6000546001600160a01b0390811691161461215c576040805162461bcd60e51b81526020600482018190526024820152600080516020613aca833981519152604482015290519081900360640190fd5b6001600160a01b0381166121a15760405162461bcd60e51b81526004018080602001828103825260268152602001806139816026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600f5481565b61220a612498565b6001600160a01b0316816001600160a01b0316141561225a5760405162461bcd60e51b8152600401808060200182810382526021815260200180613a316021913960400191505060405180910390fd5b6001600160a01b03811660009081526007602052604090205460ff16156122c657600160096000612289612498565b6001600160a01b03908116825260208083019390935260409182016000908120918616815292529020805460ff1916911515919091179055612304565b600860006122d2612498565b6001600160a01b03908116825260208083019390935260409182016000908120918516815292529020805460ff191690555b61230c612498565b6001600160a01b0316816001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a350565b61235f612359612498565b85611edb565b61239a5760405162461bcd60e51b815260040180806020018281038252602c815260200180613b7f602c913960400191505060405180910390fd5b6120ef848484846135a6565b600b546001600160a01b031681565b611ed76123c0612498565b8383604051806020016040528060008152506135a6565b6001546000906001600160a01b031633146123f3575033610f94565b6123fb6137ec565b9050610f94565b600082820183811015611f76576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061249057508115155b949350505050565b60006124a26123d7565b905090565b6001600160a01b0383166124ec5760405162461bcd60e51b81526004018080602001828103825260258152602001806139136025913960400191505060405180910390fd5b6001600160a01b0382166125315760405162461bcd60e51b8152600401808060200182810382526023815260200180613c1d6023913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6040805163555ddc6560e11b81526001600160a01b03871660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe89560248201529051600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b15801561261757600080fd5b505afa15801561262b573d6000803e3d6000fd5b505050506040513d602081101561264157600080fd5b505190506001600160a01b038116156127d257806001600160a01b03166375ab97828888888888886040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156127075781810151838201526020016126ef565b50505050905090810190601f1680156127345780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561276757818101518382015260200161274f565b50505050905090810190601f1680156127945780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b1580156127b957600080fd5b505af11580156127cd573d6000803e3d6000fd5b505050505b50505050505050565b6127e786868686613839565b61282a8360405180606001604052806027815260200161395a602791396001600160a01b038816600090815260026020526040902054919063ffffffff612a0116565b6001600160a01b03808716600090815260026020526040808220939093559086168152205461285f908463ffffffff61240216565b60026000866001600160a01b03166001600160a01b0316815260200190815260200160002081905550836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc82614677987868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156129115781810151838201526020016128f9565b50505050905090810190601f16801561293e5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612971578181015183820152602001612959565b50505050905090810190601f16801561299e5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a4836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3505050505050565b60008184841115612a905760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612a55578181015183820152602001612a3d565b50505050905090810190601f168015612a825780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6040805163555ddc6560e11b81526001600160a01b03871660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b60248201529051600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b158015612b1c57600080fd5b505afa158015612b30573d6000803e3d6000fd5b505050506040513d6020811015612b4657600080fd5b505190506001600160a01b03811615612cda57806001600160a01b03166223de298989898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612c0b578181015183820152602001612bf3565b50505050905090810190601f168015612c385780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612c6b578181015183820152602001612c53565b50505050905090810190601f168015612c985780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b158015612cbd57600080fd5b505af1158015612cd1573d6000803e3d6000fd5b50505050612d2e565b8115612d2e57612cf2866001600160a01b031661245c565b15612d2e5760405162461bcd60e51b815260040180806020018281038252604d815260200180613aea604d913960600191505060405180910390fd5b5050505050505050565b600054600160a01b900460ff16612d8d576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612dc3612498565b604080516001600160a01b039092168252519081900360200190a1565b6001600160a01b038616612e255760405162461bcd60e51b81526004018080602001828103825260228152602001806139386022913960400191505060405180910390fd5b6001600160a01b038516612e80576040805162461bcd60e51b815260206004820181905260248201527f4552433737373a2073656e6420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6000612e8a612498565b9050612e9a818888888888612593565b612ea88188888888886127db565b6127d281888888888888612a98565b50600090565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114612f66576040805162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015290519081900360640190fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612fd75760405162461bcd60e51b8152600401808060200182810382526022815260200180613a0f6022913960400191505060405180910390fd5b8060ff16601b14158015612fef57508060ff16601c14155b1561302b5760405162461bcd60e51b8152600401808060200182810382526022815260200180613a526022913960400191505060405180910390fd5b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015613083573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166130eb576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b9695505050505050565b600091565b604080516020810190915260008152600b9190910191565b600054600160a01b900460ff1615613164576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612dc3612498565b6000826131af57506000611042565b828202828482816131bc57fe5b0414611f765760405162461bcd60e51b8152600401808060200182810382526021815260200180613a746021913960400191505060405180910390fd5b6000611f7683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061389f565b6000611f7683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612a01565b6001600160a01b0384166132d8576040805162461bcd60e51b815260206004820181905260248201527f4552433737373a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b60006132e2612498565b90506132f18160008787613839565b600354613304908563ffffffff61240216565b6003556001600160a01b038516600090815260026020526040902054613330908563ffffffff61240216565b6001600160a01b03861660009081526002602052604081209190915561335d908290878787876001612a98565b846001600160a01b0316816001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156133dc5781810151838201526020016133c4565b50505050905090810190601f1680156134095780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561343c578181015183820152602001613424565b50505050905090810190601f1680156134695780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a36040805185815290516001600160a01b038716916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050565b6000806000808780602001905160808110156134dc57600080fd5b50805160208201516040830151606090930151600d549297509095509193509091506000906135209061351990620186a09063ffffffff61323b16565b8385613904565b90506000613550670de0b6b3a7640000611d53886135448c8763ffffffff61323b16565b9063ffffffff6131a016565b9050801561359a5761359a85600c60009054906101000a90046001600160a01b03168360405180602001604052806000815250604051806020016040528060008152506000612de0565b50505050505050505050565b6001600160a01b0384166135eb5760405162461bcd60e51b81526004018080602001828103825260228152602001806139c96022913960400191505060405180910390fd5b60006135f5612498565b90506136048186600087613839565b61361381866000878787612593565b61365684604051806060016040528060238152602001613bfa602391396001600160a01b038816600090815260026020526040902054919063ffffffff612a0116565b6001600160a01b038616600090815260026020526040902055600354613682908563ffffffff61323b16565b600381905550846001600160a01b0316816001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a4098868686604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156137075781810151838201526020016136ef565b50505050905090810190601f1680156137345780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561376757818101518382015260200161374f565b50505050905090810190601f1680156137945780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a36040805185815290516000916001600160a01b038816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050505050565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b613845848484846120ef565b61384d6113e0565b156120ef576040805162461bcd60e51b815260206004820152601f60248201527f5472616e7366657220666f7262696464656e207768696c652070617573656400604482015290519081900360640190fd5b600081836138ee5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612a55578181015183820152602001612a3d565b5060008385816138fa57fe5b0495945050505050565b60649081019190920202049056fe4552433737373a20617070726f76652066726f6d20746865207a65726f20616464726573734552433737373a2073656e642066726f6d20746865207a65726f20616464726573734552433737373a207472616e7366657220616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737374727573746564207369676e657220697320746865207a65726f20616464726573734552433737373a206275726e2066726f6d20746865207a65726f20616464726573734552433737373a20617574686f72697a696e672073656c66206173206f70657261746f7245434453413a20696e76616c6964207369676e6174757265202773272076616c75654552433737373a207265766f6b696e672073656c66206173206f70657261746f7245434453413a20696e76616c6964207369676e6174757265202776272076616c7565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f6e6c79207468652061637475616c2061646d696e206f70657261746f722063616e206368616e67652074686520616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433737373a20746f6b656e20726563697069656e7420636f6e747261637420686173206e6f20696d706c656d656e74657220666f7220455243373737546f6b656e73526563697069656e744552433737373a207472616e7366657220746f20746865207a65726f206164647265737347534e526563697069656e743a2063616c6c6572206973206e6f742052656c61794875624552433737373a2063616c6c6572206973206e6f7420616e206f70657261746f7220666f7220686f6c6465724552433737373a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654552433737373a207472616e736665722066726f6d20746865207a65726f20616464726573734552433737373a206275726e20616d6f756e7420657863656564732062616c616e63654552433737373a20617070726f766520746f20746865207a65726f2061646472657373a264697066735822122083f73dc8e16f32424a79641820e0d2af128ffcdba48fa94dc7634fc1ef21882264736f6c634300060a0033

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

000000000000000000000000000000000000000000315407298e1f68e96484e100000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000001e133800000000000000000000000000000000000000000000000000000000001e1338000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000fa23b0d915457fc80000000000000000000000000000000000000000000000007d11d86c8aa2bfe400000

-----Decoded View---------------
Arg [0] : initialSupply (uint256): 59634176067251733426111713
Arg [1] : _gsnTrustedSigner (address): 0x56db816b3456EDfa6edbC65F00ba45296fE136F2
Arg [2] : _gsnFeeTarget (address): 0x56db816b3456EDfa6edbC65F00ba45296fE136F2
Arg [3] : _inflationTimeSpans (uint256[]): 31536000,31536000
Arg [4] : _inflationsAmounts (uint256[]): 18900000000000000000000000,9450000000000000000000000
Arg [5] : _adminOperator (address): 0x56db816b3456EDfa6edbC65F00ba45296fE136F2

-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000315407298e1f68e96484e1
Arg [1] : 00000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f2
Arg [2] : 00000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f2
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [5] : 00000000000000000000000056db816b3456edfa6edbc65f00ba45296fe136f2
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [7] : 0000000000000000000000000000000000000000000000000000000001e13380
Arg [8] : 0000000000000000000000000000000000000000000000000000000001e13380
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [10] : 0000000000000000000000000000000000000000000fa23b0d915457fc800000
Arg [11] : 00000000000000000000000000000000000000000007d11d86c8aa2bfe400000


Deployed Bytecode Sourcemap

77742:6934:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32790:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28971:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34365:193;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34365:193:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;78258:33;;;;;;;;;;;;;;;;-1:-1:-1;78258:33:0;;:::i;:::-;;;;;;;;;;;;;;;;29765:117;;;:::i;78180:33::-;;;:::i;34934:686::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34934:686:0;;;;;;;;;;;;;;;;;:::i;78218:35::-;;;;;;;;;;;;;;;;-1:-1:-1;78218:35:0;;:::i;29412:76::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;80660:262;;;;;;;;;;;;;;;;-1:-1:-1;80660:262:0;-1:-1:-1;;;;;80660:262:0;;:::i;:::-;;80024:65;;;:::i;29610:89::-;;;:::i;80928:204::-;;;;;;;;;;;;;;;;-1:-1:-1;80928:204:0;-1:-1:-1;;;;;80928:204:0;;:::i;76813:78::-;;;:::i;33040:377::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33040:377:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33040:377:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33040:377:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33040:377:0;;;;;;;;-1:-1:-1;33040:377:0;;-1:-1:-1;;;;;33040:377:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33040:377:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33040:377:0;;-1:-1:-1;33040:377:0;;-1:-1:-1;;;;;33040:377:0:i;81555:100::-;;;;;;;;;;;;;;;;-1:-1:-1;81555:100:0;-1:-1:-1;;;;;81555:100:0;;:::i;29987:144::-;;;;;;;;;;;;;;;;-1:-1:-1;29987:144:0;-1:-1:-1;;;;;29987:144:0;;:::i;45073:148::-;;;:::i;63371:96::-;;;:::i;:::-;;;;-1:-1:-1;;;;;63371:96:0;;;;;;;;;;;;;;78102:29;;;:::i;67093:224::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;67093:224:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;67093:224:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67093:224:0;;-1:-1:-1;67093:224:0;;-1:-1:-1;;;;;67093:224:0:i;82701:1078::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;82701:1078:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82701:1078:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82701:1078:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82701:1078:0;;;;;;;;;;;;;;;-1:-1:-1;82701:1078:0;;;;;-1:-1:-1;82701:1078:0;;-1:-1:-1;82701:1078:0;;;;;;;;-1:-1:-1;;;82701:1078:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82701:1078:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82701:1078:0;;-1:-1:-1;;82701:1078:0;;;-1:-1:-1;82701:1078:0;;-1:-1:-1;;82701:1078:0:i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79956:62;;;:::i;44431:79::-;;;:::i;31829:415::-;;;;;;;;;;;;;;;;-1:-1:-1;31829:415:0;-1:-1:-1;;;;;31829:415:0;;:::i;29124:96::-;;;:::i;30268:158::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30268:158:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;30268:158:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;30268:158:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;30268:158:0;;-1:-1:-1;30268:158:0;;-1:-1:-1;;;;;30268:158:0:i;81324:99::-;;;;;;;;;;;;;;;;-1:-1:-1;81324:99:0;;:::i;30667:443::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;30667:443:0;;;;;;;;:::i;64646:230::-;;;:::i;80210:365::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80210:365:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;80210:365:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;80210:365:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;80210:365:0;;;;;;;;-1:-1:-1;80210:365:0;;-1:-1:-1;;;;;80210:365:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;80210:365:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;80210:365:0;;-1:-1:-1;80210:365:0;;-1:-1:-1;;;;;80210:365:0:i;78023:34::-;;;:::i;81661:550::-;;;:::i;82217:369::-;;;:::i;31437:320::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;31437:320:0;;;;;;;;;;:::i;77991:27::-;;;:::i;81138:180::-;;;;;;;;;;;;;;;;-1:-1:-1;81138:180:0;-1:-1:-1;;;;;81138:180:0;;:::i;34075:145::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;34075:145:0;;;;;;;;;;:::i;67974:290::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;67974:290:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;67974:290:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67974:290:0;;-1:-1:-1;;;;67974:290:0;;;;;-1:-1:-1;67974:290:0;;;;;;;;;:::i;78298:28::-;;;:::i;45376:244::-;;;;;;;;;;;;;;;;-1:-1:-1;45376:244:0;-1:-1:-1;;;;;45376:244:0;;:::i;78136:39::-;;;:::i;32313:406::-;;;;;;;;;;;;;;;;-1:-1:-1;32313:406:0;-1:-1:-1;;;;;32313:406:0;;:::i;33545:282::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33545:282:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33545:282:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33545:282:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33545:282:0;;;;;;;;-1:-1:-1;33545:282:0;;-1:-1:-1;;;;;33545:282:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;33545:282:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33545:282:0;;-1:-1:-1;33545:282:0;;-1:-1:-1;;;;;33545:282:0:i;77955:31::-;;;:::i;31247:122::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;31247:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;31247:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31247:122:0;;-1:-1:-1;31247:122:0;;-1:-1:-1;;;;;31247:122:0:i;32790:124::-;32848:16;32884:22;32877:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32877:29:0;;;;;;;;;;;;;;;;;;;;;;;32790:124;;:::o;28971:92::-;29050:5;29043:12;;;;;;;;-1:-1:-1;;29043:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29017:13;;29043:12;;29050:5;;29043:12;;29050:5;29043:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29043:12:0;;28971:92;-1:-1:-1;;;;;28971:92:0:o;34365:193::-;34439:4;34456:14;34473:12;:10;:12::i;:::-;34456:29;;34496:32;34505:6;34513:7;34522:5;34496:8;:32::i;:::-;34546:4;34539:11;;;34365:193;;;;;:::o;78258:33::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78258:33:0;:::o;29765:117::-;29862:12;;29765:117;:::o;78180:33::-;;;;:::o;34934:686::-;35032:4;-1:-1:-1;;;;;35057:23:0;;35049:72;;;;-1:-1:-1;;;35049:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35140:20:0;;35132:71;;;;-1:-1:-1;;;35132:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35216:15;35234:12;:10;:12::i;:::-;35216:30;;35259:61;35277:7;35286:6;35294:9;35305:6;35259:61;;;;;;;;;;;;;;;;;;;;;;;;:17;:61::i;:::-;35333:49;35339:7;35348:6;35356:9;35367:6;35333:49;;;;;;;;;;;;;;;;;;;;;;;;:5;:49::i;:::-;35393:112;35402:6;35410:7;35419:85;35452:6;35419:85;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35419:19:0;;;;;;;:11;:19;;;;;;;;:28;;;;;;;;;;;:85;;:32;:85;:::i;:::-;35393:8;:112::i;:::-;35518:70;35538:7;35547:6;35555:9;35566:6;35518:70;;;;;;;;;;;;;;;;;;;;;;;;35582:5;35518:19;:70::i;:::-;-1:-1:-1;35608:4:0;;34934:686;-1:-1:-1;;;;34934:686:0:o;78218:35::-;;;;;;;;;;29412:76;29478:2;29412:76;:::o;80660:262::-;80746:13;;-1:-1:-1;;;;;80746:13:0;80732:10;:27;80724:93;;;;-1:-1:-1;;;80724:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80849:13;;80829:50;;;-1:-1:-1;;;;;80849:13:0;;;80829:50;;;;;;;;;;;;;;;;;;;;;80886:13;:30;;-1:-1:-1;;;;;;80886:30:0;-1:-1:-1;;;;;80886:30:0;;;;;;;;;;80660:262::o;80024:65::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;80067:16:::1;:14;:16::i;:::-;80024:65::o:0;29610:89::-;29690:1;29610:89;:::o;80928:204::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;81013:31:0;::::1;81005:78;;;;-1:-1:-1::0;;;81005:78:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81090:16;:36:::0;;-1:-1:-1;;;;;;81090:36:0::1;-1:-1:-1::0;;;;;81090:36:0;;;::::1;::::0;;;::::1;::::0;;80928:204::o;76813:78::-;76852:4;76876:7;-1:-1:-1;;;76876:7:0;;;;;76813:78::o;33040:377::-;33256:35;33270:12;:10;:12::i;:::-;33284:6;33256:13;:35::i;:::-;33248:92;;;;-1:-1:-1;;;33248:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33351:58;33357:6;33365:9;33376:6;33384:4;33390:12;33404:4;33351:5;:58::i;:::-;33040:377;;;;;:::o;81555:100::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;81624:14:::1;:25:::0;;-1:-1:-1;;;;;;81624:25:0::1;-1:-1:-1::0;;;;;81624:25:0;;;::::1;::::0;;;::::1;::::0;;81555:100::o;29987:144::-;-1:-1:-1;;;;;30101:22:0;30074:7;30101:22;;;:9;:22;;;;;;;29987:144::o;45073:148::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;45180:1:::1;45164:6:::0;;45143:40:::1;::::0;-1:-1:-1;;;;;45164:6:0;;::::1;::::0;45143:40:::1;::::0;45180:1;;45143:40:::1;45211:1;45194:19:::0;;-1:-1:-1;;;;;;45194:19:0::1;::::0;;45073:148::o;63371:96::-;63450:9;;-1:-1:-1;;;;;63450:9:0;63371:96;:::o;78102:29::-;;;-1:-1:-1;;;;;78102:29:0;;:::o;67093:224::-;67172:7;67214:12;:10;:12::i;:::-;-1:-1:-1;;;;;67200:26:0;:10;-1:-1:-1;;;;;67200:26:0;;67192:75;;;;-1:-1:-1;;;67192:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67285:24;67301:7;67285:15;:24::i;82701:1078::-;83035:7;83044:12;83069:15;83086:22;83123:12;83112:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;83112:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;83112:39:0;;;;;;-1:-1:-1;83112:39:0;;;;;;;;;;-1:-1:-1;83112:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83068:83;;;;83158:17;83203:7;83219:5;83233:4;83246:15;83270:14;83293:8;83310;83327:5;83373:12;:10;:12::i;:::-;83444:4;83178:321;;;;;;;;;;;-1:-1:-1;;;;;83178:321:0;-1:-1:-1;;;;;83178:321:0;;;;;;;;-1:-1:-1;;;;;83178:321:0;-1:-1:-1;;;;;83178:321:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83178:321:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83178:321:0;;;;;;;;;;;;;;;;-1:-1:-1;83178:321:0;;;;;;;-1:-1:-1;83178:321:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83178:321:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83573:16;;83510:15;;;;;;;;;83178:321;;-1:-1:-1;;;;;;83573:16:0;;-1:-1:-1;83510:59:0;;-1:-1:-1;83559:9:0;;-1:-1:-1;83510:40:0;;-1:-1:-1;83510:38:0;:40::i;:::-;:48;:59;:48;:59;:::i;:::-;-1:-1:-1;;;;;83510:79:0;;83506:268;;;83627:51;;;;;;;;;-1:-1:-1;;;;;83627:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83607:72;;:19;:72::i;:::-;83600:79;;;;;;;;;83506:268;83709:57;83736:28;83709:18;:57::i;82701:1078::-;;;;;;;;;;;;;:::o;79956:62::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;79998:14:::1;:12;:14::i;44431:79::-:0;44469:7;44496:6;-1:-1:-1;;;;;44496:6:0;44431:79;:::o;31829:415::-;31926:8;-1:-1:-1;;;;;31910:24:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;31910:24:0;;;31902:73;;;;-1:-1:-1;;;31902:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;31992:27:0;;;;;;:17;:27;;;;;;;;31988:189;;;32043:24;:38;32068:12;:10;:12::i;:::-;-1:-1:-1;;;;;32043:38:0;;;;;;;;;;;;;;;;;-1:-1:-1;32043:38:0;;;:48;;;;;;;;;32036:55;;-1:-1:-1;;32036:55:0;;;31988:189;;;32161:4;32124:10;:24;32135:12;:10;:12::i;:::-;-1:-1:-1;;;;;32124:24:0;;;;;;;;;;;;;;;;;-1:-1:-1;32124:24:0;;;:34;;;;;;;;;:41;;-1:-1:-1;;32124:41:0;;;;;;;;;;31988:189;32223:12;:10;:12::i;:::-;-1:-1:-1;;;;;32194:42:0;32213:8;-1:-1:-1;;;;;32194:42:0;;;;;;;;;;;31829:415;:::o;29124:96::-;29205:7;29198:14;;;;;;;;-1:-1:-1;;29198:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29172:13;;29198:14;;29205:7;;29198:14;;29205:7;29198:14;;;;;;;;;;;;;;;;;;;;;;;;30268:158;30364:54;30370:12;:10;:12::i;:::-;30384:9;30395:6;30403:4;30364:54;;;;;;;;;;;;30413:4;30364:5;:54::i;:::-;30268:158;;;:::o;81324:99::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;81391:11:::1;:26:::0;81324:99::o;30667:443::-;30745:4;-1:-1:-1;;;;;30770:23:0;;30762:72;;;;-1:-1:-1;;;30762:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30847:12;30862;:10;:12::i;:::-;30847:27;;30887:56;30905:4;30911;30917:9;30928:6;30887:56;;;;;;;;;;;;;;;;;;;;;;;;:17;:56::i;:::-;30956:44;30962:4;30968;30974:9;30985:6;30956:44;;;;;;;;;;;;;;;;;;;;;;;;:5;:44::i;:::-;31013:65;31033:4;31039;31045:9;31056:6;31013:65;;;;;;;;;;;;;;;;;;;;;;;;31072:5;31013:19;:65::i;64646:230::-;64854:14;;;;;;;;;;;;-1:-1:-1;;;64854:14:0;;;;64646:230;:::o;80210:365::-;80406:13;;-1:-1:-1;;;;;80406:13:0;80390:12;:10;:12::i;:::-;-1:-1:-1;;;;;80390:29:0;;80382:74;;;;;-1:-1:-1;;;80382:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80463:59;80469:6;80477:9;80488:6;80496:4;80502:12;80516:5;80463;:59::i;:::-;80555:13;;80534:35;;;-1:-1:-1;;;;;80555:13:0;;;80534:35;;;;;;;;;;;;80210:365;;;;;:::o;78023:34::-;;;;:::o;81661:550::-;81767:18;;81705:17;;;81812:394;81827:3;81819:5;:11;:44;;;;-1:-1:-1;81838:18:0;:25;81834:29;;81819:44;81812:394;;;81874:14;81891:18;81910:1;81891:21;;;;;;;;;;;;;;;;;;-1:-1:-1;81939:3:0;:11;;;;82004:17;;;;82003:106;;82065:44;82102:6;82065:32;82089:7;82065:16;82082:1;82065:19;;;;;;;;;;;;;;;;:23;;:32;;;;:::i;:::-;:36;:44;:36;:44;:::i;:::-;82003:106;;;82034:16;82051:1;82034:19;;;;;;;;;;;;;;;;82003:106;81985:124;-1:-1:-1;82130:22:0;:9;81985:124;82130:22;:13;:22;:::i;:::-;82118:34;-1:-1:-1;82169:17:0;:5;82179:6;82169:17;:9;:17;:::i;:::-;82161:25;-1:-1:-1;;82195:3:0;;;;;-1:-1:-1;81812:394:0;;-1:-1:-1;81812:394:0;;81661:550;;;:::o;82217:369::-;81488:14;;-1:-1:-1;;;;;81488:14:0;81474:10;:28;81466:69;;;;;-1:-1:-1;;;81466:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;82279:15:::1;82297:14;:12;:14::i;:::-;82279:32;;82318:14;82335:37;82347:24;;82335:7;:11;;:37;;;;:::i;:::-;82318:54:::0;-1:-1:-1;82383:10:0;;82379:202:::1;;82431:24;::::0;:36:::1;::::0;82460:6;82431:36:::1;:28;:36;:::i;:::-;82404:24;:63:::0;82482:14:::1;::::0;82476:37:::1;::::0;;::::1;::::0;;::::1;::::0;;82482:14:::1;82476:37:::0;;;;;;;::::1;::::0;;;;;;::::1;::::0;-1:-1:-1;;;;;82482:14:0::1;::::0;82498:6;;82476:37;:5:::1;:37::i;:::-;82558:14;::::0;82527:46:::1;::::0;;;;;::::1;::::0;::::1;::::0;;;-1:-1:-1;;;;;82558:14:0;;::::1;82527:46:::0;;;;;::::1;::::0;;;;;;;::::1;82379:202;81542:1;;82217:369::o:0;31437:320::-;31554:4;31590:11;-1:-1:-1;;;;;31578:23:0;:8;-1:-1:-1;;;;;31578:23:0;;:121;;;-1:-1:-1;;;;;;31619:27:0;;;;;;:17;:27;;;;;;;;:79;;;;-1:-1:-1;;;;;;31651:37:0;;;;;;;:24;:37;;;;;;;;:47;;;;;;;;;;;;31650:48;31619:79;31578:171;;;-1:-1:-1;;;;;;31716:23:0;;;;;;;:10;:23;;;;;;;;:33;;;;;;;;;;;;31578:171;31571:178;31437:320;-1:-1:-1;;;31437:320:0:o;77991:27::-;;;-1:-1:-1;;;;;77991:27:0;;:::o;81138:180::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;81215:27:0;::::1;81207:70;;;::::0;;-1:-1:-1;;;81207:70:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;81284:12;:28:::0;;-1:-1:-1;;;;;;81284:28:0::1;-1:-1:-1::0;;;;;81284:28:0;;;::::1;::::0;;;::::1;::::0;;81138:180::o;34075:145::-;-1:-1:-1;;;;;34184:19:0;;;34157:7;34184:19;;;:11;:19;;;;;;;;:28;;;;;;;;;;;;;34075:145::o;67974:290::-;68133:12;:10;:12::i;:::-;-1:-1:-1;;;;;68119:26:0;:10;-1:-1:-1;;;;;68119:26:0;;68111:75;;;;-1:-1:-1;;;68111:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68197:59;68214:7;68223;68232:12;68246:9;68197:16;:59::i;:::-;67974:290;;;;:::o;78298:28::-;;;-1:-1:-1;;;;;78298:28:0;;:::o;45376:244::-;44653:12;:10;:12::i;:::-;44643:6;;-1:-1:-1;;;;;44643:6:0;;;:22;;;44635:67;;;;;-1:-1:-1;;;44635:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;44635:67:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;45465:22:0;::::1;45457:73;;;;-1:-1:-1::0;;;45457:73:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45567:6;::::0;;45546:38:::1;::::0;-1:-1:-1;;;;;45546:38:0;;::::1;::::0;45567:6;::::1;::::0;45546:38:::1;::::0;::::1;45595:6;:17:::0;;-1:-1:-1;;;;;;45595:17:0::1;-1:-1:-1::0;;;;;45595:17:0;;;::::1;::::0;;;::::1;::::0;;45376:244::o;78136:39::-;;;;:::o;32313:406::-;32403:12;:10;:12::i;:::-;-1:-1:-1;;;;;32391:24:0;:8;-1:-1:-1;;;;;32391:24:0;;;32383:70;;;;-1:-1:-1;;;32383:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32470:27:0;;;;;;:17;:27;;;;;;;;32466:189;;;32565:4;32514:24;:38;32539:12;:10;:12::i;:::-;-1:-1:-1;;;;;32514:38:0;;;;;;;;;;;;;;;;;-1:-1:-1;32514:38:0;;;:48;;;;;;;;;:55;;-1:-1:-1;;32514:55:0;;;;;;;;;;32466:189;;;32609:10;:24;32620:12;:10;:12::i;:::-;-1:-1:-1;;;;;32609:24:0;;;;;;;;;;;;;;;;;-1:-1:-1;32609:24:0;;;:34;;;;;;;;;32602:41;;-1:-1:-1;;32602:41:0;;;32466:189;32698:12;:10;:12::i;:::-;-1:-1:-1;;;;;32672:39:0;32688:8;-1:-1:-1;;;;;32672:39:0;;;;;;;;;;;32313:406;:::o;33545:282::-;33681:36;33695:12;:10;:12::i;:::-;33709:7;33681:13;:36::i;:::-;33673:93;;;;-1:-1:-1;;;33673:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33777:42;33783:7;33792:6;33800:4;33806:12;33777:5;:42::i;77955:31::-;;;-1:-1:-1;;;;;77955:31:0;;:::o;31247:122::-;31324:37;31330:12;:10;:12::i;:::-;31344:6;31352:4;31324:37;;;;;;;;;;;;:5;:37::i;65856:233::-;65964:9;;65918:15;;-1:-1:-1;;;;;65964:9:0;65950:10;:23;65946:136;;-1:-1:-1;65997:10:0;65990:17;;65946:136;66047:23;:21;:23::i;:::-;66040:30;;;;13707:181;13765:7;13797:5;;;13821:6;;;;13813:46;;;;;-1:-1:-1;;;13813:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;18940:619;19000:4;19468:20;;19311:66;19508:23;;;;;;:42;;-1:-1:-1;19535:15:0;;;19508:42;19500:51;18940:619;-1:-1:-1;;;;18940:619:0:o;79261:147::-;79346:15;79377:25;:23;:25::i;:::-;79370:32;;79261:147;:::o;39876:341::-;-1:-1:-1;;;;;39970:20:0;;39962:70;;;;-1:-1:-1;;;39962:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40051:21:0;;40043:69;;;;-1:-1:-1;;;40043:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40125:19:0;;;;;;;:11;:19;;;;;;;;:28;;;;;;;;;;;;;:36;;;40177:32;;;;;;;;;;;;;;;;;39876:341;;;:::o;40701:498::-;40954:78;;;-1:-1:-1;;;40954:78:0;;-1:-1:-1;;;;;40954:78:0;;;;;;27306:66;40954:78;;;;;;40932:19;;26827:42;;40954:41;;:78;;;;;;;;;;;;;;;26827:42;40954:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;40954:78:0;;-1:-1:-1;;;;;;41047:25:0;;;41043:149;;41103:11;-1:-1:-1;;;;;41089:39:0;;41129:8;41139:4;41145:2;41149:6;41157:8;41167:12;41089:91;;;;;;;;;;;;;-1:-1:-1;;;;;41089:91:0;-1:-1:-1;;;;;41089:91:0;;;;;;-1:-1:-1;;;;;41089:91:0;-1:-1:-1;;;;;41089:91:0;;;;;;-1:-1:-1;;;;;41089:91:0;-1:-1:-1;;;;;41089:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41089:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41043:149;40701:498;;;;;;;:::o;39187:544::-;39406:48;39427:8;39437:4;39443:2;39447:6;39406:20;:48::i;:::-;39485:70;39505:6;39485:70;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39485:15:0;;;;;;:9;:15;;;;;;;:70;;:19;:70;:::i;:::-;-1:-1:-1;;;;;39467:15:0;;;;;;;:9;:15;;;;;;:88;;;;39582:13;;;;;;;:25;;39600:6;39582:25;:17;:25;:::i;:::-;39566:9;:13;39576:2;-1:-1:-1;;;;;39566:13:0;-1:-1:-1;;;;;39566:13:0;;;;;;;;;;;;:41;;;;39646:2;-1:-1:-1;;;;;39625:56:0;39640:4;-1:-1:-1;;;;;39625:56:0;39630:8;-1:-1:-1;;;;;39625:56:0;;39650:6;39658:8;39668:12;39625:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39625:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39712:2;-1:-1:-1;;;;;39697:26:0;39706:4;-1:-1:-1;;;;;39697:26:0;;39716:6;39697:26;;;;;;;;;;;;;;;;;;39187:544;;;;;;:::o;14594:192::-;14680:7;14716:12;14708:6;;;;14700:29;;;;-1:-1:-1;;;14700:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;14752:5:0;;;14594:192::o;41901:705::-;42191:79;;;-1:-1:-1;;;42191:79:0;;-1:-1:-1;;;;;42191:79:0;;;;;;27493:66;42191:79;;;;;;42169:19;;26827:42;;42191:41;;:79;;;;;;;;;;;;;;;26827:42;42191:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42191:79:0;;-1:-1:-1;;;;;;42285:25:0;;;42281:318;;42344:11;-1:-1:-1;;;;;42327:44:0;;42372:8;42382:4;42388:2;42392:6;42400:8;42410:12;42327:96;;;;;;;;;;;;;-1:-1:-1;;;;;42327:96:0;-1:-1:-1;;;;;42327:96:0;;;;;;-1:-1:-1;;;;;42327:96:0;-1:-1:-1;;;;;42327:96:0;;;;;;-1:-1:-1;;;;;42327:96:0;-1:-1:-1;;;;;42327:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42327:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42281:318;;;42445:19;42441:158;;;42490:15;:2;-1:-1:-1;;;;;42490:13:0;;:15::i;:::-;42489:16;42481:106;;;;-1:-1:-1;;;42481:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41901:705;;;;;;;;:::o;77546:120::-;77249:7;;-1:-1:-1;;;77249:7:0;;;;77241:40;;;;;-1:-1:-1;;;77241:40:0;;;;;;;;;;;;-1:-1:-1;;;77241:40:0;;;;;;;;;;;;;;;77615:5:::1;77605:15:::0;;-1:-1:-1;;;;77605:15:0::1;::::0;;77636:22:::1;77645:12;:10;:12::i;:::-;77636:22;::::0;;-1:-1:-1;;;;;77636:22:0;;::::1;::::0;;;;;;;::::1;::::0;;::::1;77546:120::o:0;37443:674::-;-1:-1:-1;;;;;37679:18:0;;37671:65;;;;-1:-1:-1;;;37671:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37755:16:0;;37747:61;;;;;-1:-1:-1;;;37747:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37821:16;37840:12;:10;:12::i;:::-;37821:31;;37865:69;37883:8;37893:4;37899:2;37903:6;37911:8;37921:12;37865:17;:69::i;:::-;37947:57;37953:8;37963:4;37969:2;37973:6;37981:8;37991:12;37947:5;:57::i;:::-;38017:92;38037:8;38047:4;38053:2;38057:6;38065:8;38075:12;38089:19;38017;:92::i;83785:93::-;-1:-1:-1;83867:7:0;;83785:93::o;75469:269::-;75671:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75661:69;;;;;;75469:269::o;73085:2110::-;73163:7;73226:9;:16;73246:2;73226:22;73222:96;;73265:41;;;-1:-1:-1;;;73265:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;73222:96;73679:4;73664:20;;73658:27;73725:4;73710:20;;73704:27;73779:4;73764:20;;73758:27;73387:9;73750:36;74709:66;74696:79;;74692:156;;;74792:44;;-1:-1:-1;;;74792:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74692:156;74864:1;:7;;74869:2;74864:7;;:18;;;;;74875:1;:7;;74880:2;74875:7;;74864:18;74860:95;;;74899:44;;-1:-1:-1;;;74899:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74860:95;75069:24;;;75052:14;75069:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75052:14;;75069:24;;;;;;;-1:-1:-1;;75069:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;75069:24:0;;-1:-1:-1;;75069:24:0;;;-1:-1:-1;;;;;;;75112:20:0;;75104:57;;;;;-1:-1:-1;;;75104:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;75181:6;73085:2110;-1:-1:-1;;;;;;73085:2110:0:o;69176:156::-;69250:7;;69176:156::o;69468:159::-;69572:47;;;;;;;;;-1:-1:-1;69572:47:0;;62948:2;69580:34;;;;;69468:159::o;77364:118::-;77050:7;;-1:-1:-1;;;77050:7:0;;;;77049:8;77041:37;;;;;-1:-1:-1;;;77041:37:0;;;;;;;;;;;;-1:-1:-1;;;77041:37:0;;;;;;;;;;;;;;;77424:7:::1;:14:::0;;-1:-1:-1;;;;77424:14:0::1;-1:-1:-1::0;;;77424:14:0::1;::::0;;77454:20:::1;77461:12;:10;:12::i;15037:471::-:0;15095:7;15340:6;15336:47;;-1:-1:-1;15370:1:0;15363:8;;15336:47;15407:5;;;15411:1;15407;:5;:1;15431:5;;;;;:10;15423:56;;;;-1:-1:-1;;;15423:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15976:132;16034:7;16061:39;16065:1;16068;16061:39;;;;;;;;;;;;;;;;;:3;:39::i;14163:136::-;14221:7;14248:43;14252:1;14255;14248:43;;;;;;;;;;;;;;;;;:3;:43::i;36209:747::-;-1:-1:-1;;;;;36396:21:0;;36388:66;;;;;-1:-1:-1;;;36388:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36467:16;36486:12;:10;:12::i;:::-;36467:31;;36511:59;36532:8;36550:1;36554:7;36563:6;36511:20;:59::i;:::-;36633:12;;:24;;36650:6;36633:24;:16;:24;:::i;:::-;36618:12;:39;-1:-1:-1;;;;;36689:18:0;;;;;;:9;:18;;;;;;:30;;36712:6;36689:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;36668:18:0;;;;;;:9;:18;;;;;:51;;;;36732:88;;36752:8;;36678:7;36783:6;36791:8;36801:12;36815:4;36732:19;:88::i;:::-;36855:7;-1:-1:-1;;;;;36838:57:0;36845:8;-1:-1:-1;;;;;36838:57:0;;36864:6;36872:8;36882:12;36838:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36838:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36911:37;;;;;;;;-1:-1:-1;;;;;36911:37:0;;;36928:1;;36911:37;;;;;;;;;36209:747;;;;;:::o;83884:789::-;84003:15;84020:12;84034:22;84058:16;84096:7;84085:57;;;;;;;;;;;;;;;-1:-1:-1;84085:57:0;;;;;;;;;;;;;;;84463:11;;84085:57;;-1:-1:-1;84085:57:0;;-1:-1:-1;84085:57:0;;-1:-1:-1;84085:57:0;;-1:-1:-1;84392:22:0;;84417:85;;84432:43;;63067:6;;84432:43;:30;:43;:::i;:::-;84477:8;84487:14;84417;:85::i;:::-;84392:110;-1:-1:-1;84509:8:0;84520:64;77864:6;84520:45;84557:7;84520:32;:12;84392:110;84520:32;:16;:32;:::i;:::-;:36;:45;:36;:45;:::i;:64::-;84509:75;-1:-1:-1;84597:7:0;;84593:75;;84615:45;84621:4;84627:12;;;;;;;;;-1:-1:-1;;;;;84627:12:0;84641:3;84615:45;;;;;;;;;;;;;;;;;;;;;;;;84654:5;84615;:45::i;:::-;83884:789;;;;;;;;;;:::o;38431:748::-;-1:-1:-1;;;;;38615:18:0;;38607:65;;;;-1:-1:-1;;;38607:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38685:16;38704:12;:10;:12::i;:::-;38685:31;;38729:56;38750:8;38760:4;38774:1;38778:6;38729:20;:56::i;:::-;38798:73;38816:8;38826:4;38840:1;38844:6;38852:4;38858:12;38798:17;:73::i;:::-;38937:66;38957:6;38937:66;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38937:15:0;;;;;;:9;:15;;;;;;;:66;;:19;:66;:::i;:::-;-1:-1:-1;;;;;38919:15:0;;;;;;:9;:15;;;;;:84;39029:12;;:24;;39046:6;39029:24;:16;:24;:::i;:::-;39014:12;:39;;;;39088:4;-1:-1:-1;;;;;39071:50:0;39078:8;-1:-1:-1;;;;;39071:50:0;;39094:6;39102:4;39108:12;39071:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39071:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39137:34;;;;;;;;39160:1;;-1:-1:-1;;;;;39137:34:0;;;;;;;;;;;;38431:748;;;;;:::o;70143:1270::-;70198:22;71016:18;71037:8;;71016:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;71072:8:0;71308:17;71302:24;-1:-1:-1;;;;;71298:73:0;;70143:1270;-1:-1:-1;;70143:1270:0:o;79705:245::-;79829:55;79856:8;79866:4;79872:2;79876:7;79829:26;:55::i;:::-;79900:8;:6;:8::i;:::-;79899:9;79891:53;;;;;-1:-1:-1;;;79891:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;16596:345;16682:7;16784:12;16777:5;16769:28;;;;-1:-1:-1;;;16769:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16808:9;16824:1;16820;:5;;;;;;;16596:345;-1:-1:-1;;;;;16596:345:0:o;69791:344::-;70124:3;70103:16;;;70085:14;;;;:35;70084:43;;69791:344::o

Swarm Source

ipfs://83f73dc8e16f32424a79641820e0d2af128ffcdba48fa94dc7634fc1ef218822
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.