ETH Price: $3,349.51 (-0.77%)

Token

AVASTAR Token (AVASTAR)
 

Overview

Max Total Supply

26,617 AVASTAR

Holders

5,083

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
2 AVASTAR
0xf450a188A00a82CA95FdfF613A34aafB81a7C5d0
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Generative Art Stored Entirely On The Blockchain.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
AvastarTeleporter

Compiler Version
v0.5.14+commit.1f1aaa4

Optimization Enabled:
Yes with 200 runs

Other Settings:
istanbul EvmVersion, None license, Audited

Contract Source Code (Solidity)Audit Report

/**
 *Submitted for verification at Etherscan.io on 2020-02-07
*/

// File: contracts/AvastarTypes.sol

pragma solidity 0.5.14;

/**
 * @title Avastar Data Types
 * @author Cliff Hall
 */
contract AvastarTypes {

    enum Generation {
        ONE,
        TWO,
        THREE,
        FOUR,
        FIVE
    }

    enum Series {
        PROMO,
        ONE,
        TWO,
        THREE,
        FOUR,
        FIVE
    }

    enum Wave {
        PRIME,
        REPLICANT
    }

    enum Gene {
        SKIN_TONE,
        HAIR_COLOR,
        EYE_COLOR,
        BG_COLOR,
        BACKDROP,
        EARS,
        FACE,
        NOSE,
        MOUTH,
        FACIAL_FEATURE,
        EYES,
        HAIR_STYLE
    }

    enum Gender {
        ANY,
        MALE,
        FEMALE
    }

    enum Rarity {
        COMMON,
        UNCOMMON,
        RARE,
        EPIC,
        LEGENDARY
    }

    struct Trait {
        uint256 id;
        Generation generation;
        Gender gender;
        Gene gene;
        Rarity rarity;
        uint8 variation;
        Series[] series;
        string name;
        string svg;

    }

    struct Prime {
        uint256 id;
        uint256 serial;
        uint256 traits;
        bool[12] replicated;
        Generation generation;
        Series series;
        Gender gender;
        uint8 ranking;
    }

    struct Replicant {
        uint256 id;
        uint256 serial;
        uint256 traits;
        Generation generation;
        Gender gender;
        uint8 ranking;
    }

    struct Avastar {
        uint256 id;
        uint256 serial;
        uint256 traits;
        Generation generation;
        Wave wave;
    }

    struct Attribution {
        Generation generation;
        string artist;
        string infoURI;
    }

}

// File: contracts/AvastarBase.sol

pragma solidity 0.5.14;

/**
 * @title Avastar Base
 * @author Cliff Hall
 * @notice Utilities used by descendant contracts
 */
contract AvastarBase {

    /**
     * @notice Convert a `uint` value to a `string`
     * via OraclizeAPI - MIT licence
     * https://github.com/provable-things/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol#L896
     * @param _i the `uint` value to be converted
     * @return result the `string` representation of the given `uint` value
     */
    function uintToStr(uint _i)
    internal pure
    returns (string memory result) {
        if (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (_i != 0) {
            bstr[k--] = byte(uint8(48 + _i % 10));
            _i /= 10;
        }
        result = string(bstr);
    }

    /**
     * @notice Concatenate two strings
     * @param _a the first string
     * @param _b the second string
     * @return result the concatenation of `_a` and `_b`
     */
    function strConcat(string memory _a, string memory _b)
    internal pure
    returns(string memory result) {
        result = string(abi.encodePacked(bytes(_a), bytes(_b)));
    }

}

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

pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

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

pragma solidity ^0.5.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.
     *
     * _Available since v2.4.0._
     */
    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.
     *
     * _Available since v2.4.0._
     */
    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.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: contracts/AccessControl.sol

pragma solidity 0.5.14;



/**
 * @title Access Control
 * @author Cliff Hall
 * @notice Role-based access control and contract upgrade functionality.
 */
contract AccessControl {

    using SafeMath for uint256;
    using SafeMath for uint16;
    using Roles for Roles.Role;

    Roles.Role private admins;
    Roles.Role private minters;
    Roles.Role private owners;

    /**
     * @notice Sets `msg.sender` as system admin by default.
     * Starts paused. System admin must unpause, and add other roles after deployment.
     */
    constructor() public {
        admins.add(msg.sender);
    }

    /**
     * @notice Emitted when contract is paused by system administrator.
     */
    event ContractPaused();

    /**
     * @notice Emitted when contract is unpaused by system administrator.
     */
    event ContractUnpaused();

    /**
     * @notice Emitted when contract is upgraded by system administrator.
     * @param newContract address of the new version of the contract.
     */
    event ContractUpgrade(address newContract);


    bool public paused = true;
    bool public upgraded = false;
    address public newContractAddress;

    /**
     * @notice Modifier to scope access to minters
     */
    modifier onlyMinter() {
        require(minters.has(msg.sender));
        _;
    }

    /**
     * @notice Modifier to scope access to owners
     */
    modifier onlyOwner() {
        require(owners.has(msg.sender));
        _;
    }

    /**
     * @notice Modifier to scope access to system administrators
     */
    modifier onlySysAdmin() {
        require(admins.has(msg.sender));
        _;
    }

    /**
     * @notice Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /**
     * @notice Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(paused);
        _;
    }

    /**
     * @notice Modifier to make a function callable only when the contract not upgraded.
     */
    modifier whenNotUpgraded() {
        require(!upgraded);
        _;
    }

    /**
     * @notice Called by a system administrator to  mark the smart contract as upgraded,
     * in case there is a serious breaking bug. This method stores the new contract
     * address and emits an event to that effect. Clients of the contract should
     * update to the new contract address upon receiving this event. This contract will
     * remain paused indefinitely after such an upgrade.
     * @param _newAddress address of new contract
     */
    function upgradeContract(address _newAddress) external onlySysAdmin whenPaused whenNotUpgraded {
        require(_newAddress != address(0));
        upgraded = true;
        newContractAddress = _newAddress;
        emit ContractUpgrade(_newAddress);
    }

    /**
     * @notice Called by a system administrator to add a minter.
     * Reverts if `_minterAddress` already has minter role
     * @param _minterAddress approved minter
     */
    function addMinter(address _minterAddress) external onlySysAdmin {
        minters.add(_minterAddress);
        require(minters.has(_minterAddress));
    }

    /**
     * @notice Called by a system administrator to add an owner.
     * Reverts if `_ownerAddress` already has owner role
     * @param _ownerAddress approved owner
     * @return added boolean indicating whether the role was granted
     */
    function addOwner(address _ownerAddress) external onlySysAdmin {
        owners.add(_ownerAddress);
        require(owners.has(_ownerAddress));
    }

    /**
     * @notice Called by a system administrator to add another system admin.
     * Reverts if `_sysAdminAddress` already has sysAdmin role
     * @param _sysAdminAddress approved owner
     */
    function addSysAdmin(address _sysAdminAddress) external onlySysAdmin {
        admins.add(_sysAdminAddress);
        require(admins.has(_sysAdminAddress));
    }

    /**
     * @notice Called by an owner to remove all roles from an address.
     * Reverts if address had no roles to be removed.
     * @param _address address having its roles stripped
     */
    function stripRoles(address _address) external onlyOwner {
        require(msg.sender != _address);
        bool stripped = false;
        if (admins.has(_address)) {
            admins.remove(_address);
            stripped = true;
        }
        if (minters.has(_address)) {
            minters.remove(_address);
            stripped = true;
        }
        if (owners.has(_address)) {
            owners.remove(_address);
            stripped = true;
        }
        require(stripped == true);
    }

    /**
     * @notice Called by a system administrator to pause, triggers stopped state
     */
    function pause() external onlySysAdmin whenNotPaused {
        paused = true;
        emit ContractPaused();
    }

    /**
     * @notice Called by a system administrator to un-pause, returns to normal state
     */
    function unpause() external onlySysAdmin whenPaused whenNotUpgraded {
        paused = false;
        emit ContractUnpaused();
    }

}

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

pragma solidity ^0.5.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 { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view 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/introspection/IERC165.sol

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol

pragma solidity ^0.5.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of NFTs in `owner`'s account.
     */
    function balanceOf(address owner) public view returns (uint256 balance);

    /**
     * @dev Returns the owner of the NFT specified by `tokenId`.
     */
    function ownerOf(uint256 tokenId) public view returns (address owner);

    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     *
     *
     * Requirements:
     * - `from`, `to` cannot be zero.
     * - `tokenId` must be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this
     * NFT by either {approve} or {setApprovalForAll}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public;
    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     * Requirements:
     * - If the caller is not `from`, it must be approved to move this NFT by
     * either {approve} or {setApprovalForAll}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public;
    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);


    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol

pragma solidity ^0.5.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
    public returns (bytes4);
}

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

pragma solidity ^0.5.5;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing 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.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        // 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 != 0x0 && codehash != accountHash);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    /**
     * @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].
     *
     * _Available since v2.4.0._
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

// File: @openzeppelin/contracts/drafts/Counters.sol

pragma solidity ^0.5.0;


/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
 * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
 * directly accessed.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}

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

pragma solidity ^0.5.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

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

pragma solidity ^0.5.0;








/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721 {
    using SafeMath for uint256;
    using Address for address;
    using Counters for Counters.Counter;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from token ID to owner
    mapping (uint256 => address) private _tokenOwner;

    // Mapping from token ID to approved address
    mapping (uint256 => address) private _tokenApprovals;

    // Mapping from owner to number of owned token
    mapping (address => Counters.Counter) private _ownedTokensCount;

    // Mapping from owner to operator approvals
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    constructor () public {
        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address owner) public view returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        return _ownedTokensCount[owner].current();
    }

    /**
     * @dev Gets the owner of the specified token ID.
     * @param tokenId uint256 ID of the token to query the owner of
     * @return address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 tokenId) public view returns (address) {
        address owner = _tokenOwner[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");

        return owner;
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param to address to be approved for the given token ID
     * @param tokenId uint256 ID of the token to be approved
     */
    function approve(address to, uint256 tokenId) public {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 tokenId) public view returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf.
     * @param to operator address to set the approval
     * @param approved representing the status of the approval to be set
     */
    function setApprovalForAll(address to, bool approved) public {
        require(to != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][to] = approved;
        emit ApprovalForAll(_msgSender(), to, approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner.
     * @param owner owner address which you want to query the approval of
     * @param operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address owner, address operator) public view returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address.
     * Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     * Requires the msg.sender to be the owner, approved, or operator.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function transferFrom(address from, address to, uint256 tokenId) public {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transferFrom(from, to, tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the _msgSender() to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransferFrom(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal {
        _transferFrom(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether the specified token exists.
     * @param tokenId uint256 ID of the token to query the existence of
     * @return bool whether the token exists
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        address owner = _tokenOwner[tokenId];
        return owner != address(0);
    }

    /**
     * @dev Returns whether the given spender can transfer a given token ID.
     * @param spender address of the spender to query
     * @param tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     * is an operator of the owner, or is the owner of the token
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _safeMint(address to, uint256 tokenId) internal {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Internal function to mint a new token.
     * Reverts if the given token ID already exists.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _tokenOwner[tokenId] = to;
        _ownedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use {_burn} instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");

        _clearApproval(tokenId);

        _ownedTokensCount[owner].decrement();
        _tokenOwner[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(uint256 tokenId) internal {
        _burn(ownerOf(tokenId), tokenId);
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(address from, address to, uint256 tokenId) internal {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _clearApproval(tokenId);

        _ownedTokensCount[from].decrement();
        _ownedTokensCount[to].increment();

        _tokenOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * This function is deprecated.
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        internal returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }

        bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data);
        return (retval == _ERC721_RECEIVED);
    }

    /**
     * @dev Private function to clear current approval of a given token ID.
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _clearApproval(uint256 tokenId) private {
        if (_tokenApprovals[tokenId] != address(0)) {
            _tokenApprovals[tokenId] = address(0);
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol

pragma solidity ^0.5.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721Enumerable is IERC721 {
    function totalSupply() public view returns (uint256);
    function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);

    function tokenByIndex(uint256 index) public view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/ERC721Enumerable.sol

pragma solidity ^0.5.0;





/**
 * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => uint256[]) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    /**
     * @dev Constructor function.
     */
    constructor () public {
        // register the supported interface to conform to ERC721Enumerable via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @dev Gets the token ID at a given index of the tokens list of the requested owner.
     * @param owner address owning the tokens list to be accessed
     * @param index uint256 representing the index to be accessed of the requested tokens list
     * @return uint256 token ID at the given index of the tokens list owned by the requested address
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
        require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract.
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens.
     * @param index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 index) public view returns (uint256) {
        require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to transferFrom, this imposes no restrictions on msg.sender.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(address from, address to, uint256 tokenId) internal {
        super._transferFrom(from, to, tokenId);

        _removeTokenFromOwnerEnumeration(from, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);
    }

    /**
     * @dev Internal function to mint a new token.
     * Reverts if the given token ID already exists.
     * @param to address the beneficiary that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        super._mint(to, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);

        _addTokenToAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use {ERC721-_burn} instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        super._burn(owner, tokenId);

        _removeTokenFromOwnerEnumeration(owner, tokenId);
        // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
        _ownedTokensIndex[tokenId] = 0;

        _removeTokenFromAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Gets the list of token IDs of the requested owner.
     * @param owner address owning the tokens
     * @return uint256[] List of token IDs owned by the requested address
     */
    function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
        return _ownedTokens[owner];
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
        _ownedTokens[to].push(tokenId);
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        _ownedTokens[from].length--;

        // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
        // lastTokenId, or just over the end of the array if the token was the last one).
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length.sub(1);
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        _allTokens.length--;
        _allTokensIndex[tokenId] = 0;
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol

pragma solidity ^0.5.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/token/ERC721/ERC721Metadata.sol

pragma solidity ^0.5.0;





contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /**
     * @dev Constructor function
     */
    constructor (string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
    }

    /**
     * @dev Gets the token name.
     * @return string representing the token name
     */
    function name() external view returns (string memory) {
        return _name;
    }

    /**
     * @dev Gets the token symbol.
     * @return string representing the token symbol
     */
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns an URI for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query
     */
    function tokenURI(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
        return _tokenURIs[tokenId];
    }

    /**
     * @dev Internal function to set the token URI for a given token.
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to set its URI
     * @param uri string URI to assign
     */
    function _setTokenURI(uint256 tokenId, string memory uri) internal {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = uri;
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use _burn(uint256) instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned by the msg.sender
     */
    function _burn(address owner, uint256 tokenId) internal {
        super._burn(owner, tokenId);

        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/ERC721Full.sol

pragma solidity ^0.5.0;




/**
 * @title Full ERC721 Token
 * @dev This implementation includes all the required and some optional functionality of the ERC721 standard
 * Moreover, it includes approve all functionality using operator terminology.
 *
 * See https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
    constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) {
        // solhint-disable-previous-line no-empty-blocks
    }
}

// File: contracts/AvastarState.sol

pragma solidity 0.5.14;





/**
 * @title Avastar State
 * @author Cliff Hall
 * @notice This contract maintains the state variables for the Avastar Teleporter.
 */
contract AvastarState is AvastarBase, AvastarTypes, AccessControl, ERC721Full {

    /**
     * @notice Calls ERC721Full constructor with token name and symbol.
     */
    constructor() public ERC721Full(TOKEN_NAME, TOKEN_SYMBOL) {}

    string public constant TOKEN_NAME = "Avastar";
    string public constant TOKEN_SYMBOL = "AVASTAR";

    /**
     * @notice All Avastars across all Waves and Generations
     */
    Avastar[] internal avastars;

    /**
     * @notice List of all Traits across all Generations
     */
    Trait[] internal traits;

    /**
     * @notice  Retrieve Primes by Generation
     * Prime[] primes = primesByGeneration[uint8(_generation)]
     */
    mapping(uint8 => Prime[]) internal primesByGeneration;

    /**
     * @notice Retrieve Replicants by Generation
     * Replicant[] replicants = replicantsByGeneration[uint8(_generation)]
     */
    mapping(uint8 => Replicant[]) internal replicantsByGeneration;

    /**
     * @notice Retrieve Artist Attribution by Generation
     * Attribution attribution = attributionByGeneration[Generation(_generation)]
     */
    mapping(uint8 => Attribution) public attributionByGeneration;

    /**
     * @notice Retrieve the approved Trait handler for a given Avastar Prime by Token ID
     */
    mapping(uint256 => address) internal traitHandlerByPrimeTokenId;

    /**
     * @notice Is a given Trait Hash used within a given Generation
     * bool used = isHashUsedByGeneration[uint8(_generation)][uint256(_traits)]
     * This mapping ensures that within a Generation, a given Trait Hash is unique and can only be used once
     */
    mapping(uint8 => mapping(uint256 => bool)) public isHashUsedByGeneration;

    /**
     * @notice Retrieve Token ID for a given Trait Hash within a given Generation
     * uint256 tokenId = tokenIdByGenerationAndHash[uint8(_generation)][uint256(_traits)]
     * Since Token IDs start at 0 and empty mappings for uint256 return 0, check isHashUsedByGeneration first
     */
    mapping(uint8 => mapping(uint256 => uint256)) public tokenIdByGenerationAndHash;

    /**
     * @notice Retrieve count of Primes and Promos by Generation and Series
     * uint16 count = primeCountByGenAndSeries[uint8(_generation)][uint8(_series)]
     */
    mapping(uint8 =>  mapping(uint8 => uint16)) public primeCountByGenAndSeries;

    /**
     * @notice Retrieve count of Replicants by Generation
     * uint16 count = replicantCountByGeneration[uint8(_generation)]
     */
    mapping(uint8 => uint16) public replicantCountByGeneration;

    /**
     * @notice Retrieve the Token ID for an Avastar by a given Generation, Wave, and Serial
     * uint256 tokenId = tokenIdByGenerationWaveAndSerial[uint8(_generation)][uint256(_wave)][uint256(_serial)]
     */
    mapping(uint8 => mapping(uint8 => mapping(uint256 => uint256))) public tokenIdByGenerationWaveAndSerial;

    /**
     * @notice Retrieve the Trait ID for a Trait from a given Generation by Gene and Variation
     * uint256 traitId = traitIdByGenerationGeneAndVariation[uint8(_generation)][uint8(_gene)][uint8(_variation)]
     */
    mapping(uint8 => mapping(uint8 => mapping(uint8 => uint256))) public traitIdByGenerationGeneAndVariation;

}

// File: contracts/TraitFactory.sol

pragma solidity 0.5.14;


/**
 * @title Avastar Trait Factory
 * @author Cliff Hall
 */
contract TraitFactory is AvastarState {

    /**
     * @notice Event emitted when a new Trait is created.
     * @param id the Trait ID
     * @param generation the generation of the trait
     * @param gene the gene that the trait is a variation of
     * @param rarity the rarity level of this trait
     * @param variation variation of the gene the trait represents
     * @param name the name of the trait
     */
    event NewTrait(uint256 id, Generation generation, Gene gene, Rarity rarity, uint8 variation, string name);

    /**
     * @notice Event emitted when artist attribution is set for a generation.
     * @param generation the generation that attribution was set for
     * @param artist the artist who created the artwork for the generation
     * @param infoURI the artist's website / portfolio URI
     */
    event AttributionSet(Generation generation, string artist, string infoURI);

    /**
     * @notice Event emitted when a Trait's art is created.
     * @param id the Trait ID
     */
    event TraitArtExtended(uint256 id);

    /**
     * @notice Modifier to ensure no trait modification after a generation's
     * Avastar production has begun.
     * @param _generation the generation to check production status of
     */
    modifier onlyBeforeProd(Generation _generation) {
        require(primesByGeneration[uint8(_generation)].length == 0 && replicantsByGeneration[uint8(_generation)].length == 0);
        _;
    }

    /**
     * @notice Get Trait ID by Generation, Gene, and Variation.
     * @param _generation the generation the trait belongs to
     * @param _gene gene the trait belongs to
     * @param _variation the variation of the gene
     * @return traitId the ID of the specified trait
     */
    function getTraitIdByGenerationGeneAndVariation(
        Generation _generation,
        Gene _gene,
        uint8 _variation
    )
    external view
    returns (uint256 traitId)
    {
        return traitIdByGenerationGeneAndVariation[uint8(_generation)][uint8(_gene)][_variation];
    }

    /**
     * @notice Retrieve a Trait's info by ID.
     * @param _traitId the ID of the Trait to retrieve
     * @return id the ID of the trait
     * @return generation generation of the trait
     * @return series list of series the trait may appear in
     * @return gender gender(s) the trait is valid for
     * @return gene gene the trait belongs to
     * @return variation variation of the gene the trait represents
     * @return rarity the rarity level of this trait
     * @return name name of the trait
     */
    function getTraitInfoById(uint256 _traitId)
    external view
    returns (
        uint256 id,
        Generation generation,
        Series[] memory series,
        Gender gender,
        Gene gene,
        Rarity rarity,
        uint8 variation,
        string memory name
    ) {
        require(_traitId < traits.length);
        Trait memory trait = traits[_traitId];
        return (
            trait.id,
            trait.generation,
            trait.series,
            trait.gender,
            trait.gene,
            trait.rarity,
            trait.variation,
            trait.name
        );
    }

    /**
     * @notice Retrieve a Trait's name by ID.
     * @param _traitId the ID of the Trait to retrieve
     * @return name name of the trait
     */
    function getTraitNameById(uint256 _traitId)
    external view
    returns (string memory name) {
        require(_traitId < traits.length);
        name = traits[_traitId].name;
    }

    /**
     * @notice Retrieve a Trait's art by ID.
     * Only invokable by a system administrator.
     * @param _traitId the ID of the Trait to retrieve
     * @return art the svg layer representation of the trait
     */
    function getTraitArtById(uint256 _traitId)
    external view onlySysAdmin
    returns (string memory art) {
        require(_traitId < traits.length);
        Trait memory trait = traits[_traitId];
        art = trait.svg;
    }

    /**
     * @notice Get the artist Attribution info for a given Generation, combined into a single string.
     * @param _generation the generation to retrieve artist attribution for
     * @return attrib a single string with the artist and artist info URI
     */
    function getAttributionByGeneration(Generation _generation)
    external view
    returns (
        string memory attribution
    ){
        Attribution memory attrib = attributionByGeneration[uint8(_generation)];
        require(bytes(attrib.artist).length > 0);
        attribution = strConcat(attribution, attrib.artist);
        attribution = strConcat(attribution, ' (');
        attribution = strConcat(attribution, attrib.infoURI);
        attribution = strConcat(attribution, ')');
    }

    /**
     * @notice Set the artist Attribution for a given Generation
     * @param _generation the generation to set artist attribution for
     * @param _artist the artist who created the art for the generation
     * @param _infoURI the URI for the artist's website / portfolio
     */
    function setAttribution(
        Generation _generation,
        string calldata _artist,
        string calldata _infoURI
    )
    external onlySysAdmin onlyBeforeProd(_generation)
    {
        require(bytes(_artist).length > 0 && bytes(_infoURI).length > 0);
        attributionByGeneration[uint8(_generation)] = Attribution(_generation, _artist, _infoURI);
        emit AttributionSet(_generation, _artist, _infoURI);
    }

    /**
     * @notice Create a Trait
     * @param _generation the generation the trait belongs to
     * @param _series list of series the trait may appear in
     * @param _gender gender the trait is valid for
     * @param _gene gene the trait belongs to
     * @param _rarity the rarity level of this trait
     * @param _variation the variation of the gene the trait belongs to
     * @param _name the name of the trait
     * @param _svg svg layer representation of the trait
     * @return traitId the token ID of the newly created trait
     */
    function createTrait(
        Generation _generation,
        Series[] calldata _series,
        Gender _gender,
        Gene _gene,
        Rarity _rarity,
        uint8 _variation,
        string calldata _name,
        string calldata _svg
    )
    external onlySysAdmin whenNotPaused onlyBeforeProd(_generation)
    returns (uint256 traitId)
    {
        require(_series.length > 0);
        require(bytes(_name).length > 0);
        require(bytes(_svg).length > 0);

        // Get Trait ID
        traitId = traits.length;

        // Create and store trait
        traits.push(
            Trait(traitId, _generation, _gender, _gene, _rarity, _variation,  _series, _name, _svg)
        );

        // Create generation/gene/variation to traitId mapping required by assembleArtwork
        traitIdByGenerationGeneAndVariation[uint8(_generation)][uint8(_gene)][uint8(_variation)] = traitId;

        // Send the NewTrait event
        emit NewTrait(traitId, _generation, _gene, _rarity, _variation, _name);

        // Return the new Trait ID
        return traitId;
    }

    /**
     * @notice Extend a Trait's art.
     * Only invokable by a system administrator.
     * If successful, emits a `TraitArtExtended` event with the resultant artwork.
     * @param _traitId the ID of the Trait to retrieve
     * @param _svg the svg content to be concatenated to the existing svg property
     */
    function extendTraitArt(uint256 _traitId, string calldata _svg)
    external onlySysAdmin whenNotPaused onlyBeforeProd(traits[_traitId].generation)
    {
        require(_traitId < traits.length);
        string memory art = strConcat(traits[_traitId].svg, _svg);
        traits[_traitId].svg = art;
        emit TraitArtExtended(_traitId);
    }

    /**
     * @notice Assemble the artwork for a given Trait hash with art from the given Generation
     * @param _generation the generation the Avastar belongs to
     * @param _traitHash the Avastar's trait hash
     * @return svg the fully rendered SVG for the Avastar
     */
    function assembleArtwork(Generation _generation, uint256 _traitHash)
    internal view
    returns (string memory svg)
    {
        require(_traitHash > 0);
        string memory accumulator = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="1000px" width="1000px" viewBox="0 0 1000 1000">';
        uint256 slotConst = 256;
        uint256 slotMask = 255;
        uint256 bitMask;
        uint256 slottedValue;
        uint256 slotMultiplier;
        uint256 variation;
        uint256 traitId;
        Trait memory trait;

        // Iterate trait hash by Gene and assemble SVG sandwich
        for (uint8 slot = 0; slot <= uint8(Gene.HAIR_STYLE); slot++){
            slotMultiplier = uint256(slotConst**slot);  // Create slot multiplier
            bitMask = slotMask * slotMultiplier;        // Create bit mask for slot
            slottedValue = _traitHash & bitMask;        // Extract slotted value from hash
            if (slottedValue > 0) {
                variation = (slot > 0)                  // Extract variation from slotted value
                    ? slottedValue / slotMultiplier
                    : slottedValue;
                if (variation > 0) {
                    traitId = traitIdByGenerationGeneAndVariation[uint8(_generation)][slot][uint8(variation)];
                    trait = traits[traitId];
                    accumulator = strConcat(accumulator, trait.svg);
                }
            }
        }

        return strConcat(accumulator, '</svg>');
    }

}

// File: contracts/AvastarFactory.sol

pragma solidity 0.5.14;


/**
 * @title Avastar Token Factory
 * @author Cliff Hall
 */
contract AvastarFactory is TraitFactory {

    /**
     * @notice Mint an Avastar.
     * Only invokable by descendant contracts when contract is not paused.
     * Adds new `Avastar` to `avastars` array.
     * Doesn't emit an event, the calling method does (`NewPrime` or `NewReplicant`).
     * Sets `isHashUsedByGeneration` mapping to true for `avastar.generation` and `avastar.traits`.
     * Sets `tokenIdByGenerationAndHash` mapping to `avastar.id` for `avastar.generation` and `avastar.traits`.
     * Sets `tokenIdByGenerationWaveAndSerial` mapping to `avastar.id` for `avastar.generation`, `avastar.wave`, and `avastar.serial`.
     * @param _owner the address of the new Avastar's owner
     * @param _serial the new Avastar's Prime or Replicant serial number
     * @param _traits the new Avastar's trait hash
     * @param _generation the new Avastar's generation
     * @param _wave the new Avastar's wave (Prime/Replicant)
     * @return tokenId the newly minted Prime's token ID
     */
    function mintAvastar(
        address _owner,
        uint256 _serial,
        uint256 _traits,
        Generation _generation,
        Wave _wave
    )
    internal whenNotPaused
    returns (uint256 tokenId)
    {
        // Mapped Token Id for given generation and serial should always be 0 (uninitialized)
        require(tokenIdByGenerationWaveAndSerial[uint8(_generation)][uint8(_wave)][_serial] == 0);

        // Serial should always be the current length of the primes or replicants array for the given generation
        if (_wave == Wave.PRIME){
            require(_serial == primesByGeneration[uint8(_generation)].length);
        } else {
            require(_serial == replicantsByGeneration[uint8(_generation)].length);
        }

        // Get Token ID
        tokenId = avastars.length;

        // Create and store Avastar token
        Avastar memory avastar = Avastar(tokenId, _serial, _traits, _generation, _wave);

        // Store the avastar
        avastars.push(avastar);

        // Indicate use of Trait Hash within given generation
        isHashUsedByGeneration[uint8(avastar.generation)][avastar.traits] = true;

        // Store token ID by Generation and Trait Hash
        tokenIdByGenerationAndHash[uint8(avastar.generation)][avastar.traits] = avastar.id;

        // Create generation/wave/serial to tokenId mapping
        tokenIdByGenerationWaveAndSerial[uint8(avastar.generation)][uint8(avastar.wave)][avastar.serial] = avastar.id;

        // Mint the token
        super._mint(_owner, tokenId);
    }

    /**
     * @notice Get an Avastar's Wave by token ID.
     * @param _tokenId the token id of the given Avastar
     * @return wave the Avastar's wave (Prime/Replicant)
     */
    function getAvastarWaveByTokenId(uint256 _tokenId)
    external view
    returns (Wave wave)
    {
        require(_tokenId < avastars.length);
        wave = avastars[_tokenId].wave;
    }

    /**
     * @notice Render the Avastar Prime or Replicant from the original on-chain art.
     * @param _tokenId the token ID of the Prime or Replicant
     * @return svg the fully rendered SVG representation of the Avastar
     */
    function renderAvastar(uint256 _tokenId)
    external view
    returns (string memory svg)
    {
        require(_tokenId < avastars.length);
        Avastar memory avastar = avastars[_tokenId];
        uint256 traits = (avastar.wave == Wave.PRIME)
        ? primesByGeneration[uint8(avastar.generation)][avastar.serial].traits
        : replicantsByGeneration[uint8(avastar.generation)][avastar.serial].traits;
        svg = assembleArtwork(avastar.generation, traits);
    }
}

// File: contracts/PrimeFactory.sol

pragma solidity 0.5.14;


/**
 * @title Avastar Prime Factory
 * @author Cliff Hall
 */
contract PrimeFactory is AvastarFactory {

    /**
     * @notice Maximum number of primes that can be minted in
     * any given series for any generation.
     */
    uint16 public constant MAX_PRIMES_PER_SERIES = 5000;
    uint16 public constant MAX_PROMO_PRIMES_PER_GENERATION = 200;

    /**
     * @notice Event emitted upon the creation of an Avastar Prime
     * @param id the token ID of the newly minted Prime
     * @param serial the serial of the Prime
     * @param generation the generation of the Prime
     * @param series the series of the Prime
     * @param gender the gender of the Prime
     * @param traits the trait hash of the Prime
     */
    event NewPrime(uint256 id, uint256 serial, Generation generation, Series series, Gender gender, uint256 traits);

    /**
     * @notice Get the Avastar Prime metadata associated with a given Generation and Serial.
     * Does not include the trait replication flags.
     * @param _generation the Generation of the Prime
     * @param _serial the Serial of the Prime
     * @return tokenId the Prime's token ID
     * @return serial the Prime's serial
     * @return traits the Prime's trait hash
     * @return replicated the Prime's trait replication indicators
     * @return generation the Prime's generation
     * @return series the Prime's series
     * @return gender the Prime's gender
     * @return ranking the Prime's ranking
     */
    function getPrimeByGenerationAndSerial(Generation _generation, uint256 _serial)
    external view
    returns (
        uint256 tokenId,
        uint256 serial,
        uint256 traits,
        Generation generation,
        Series series,
        Gender gender,
        uint8 ranking
    ) {
        require(_serial < primesByGeneration[uint8(_generation)].length);
        Prime memory prime = primesByGeneration[uint8(_generation)][_serial];
        return (
            prime.id,
            prime.serial,
            prime.traits,
            prime.generation,
            prime.series,
            prime.gender,
            prime.ranking
        );
    }

    /**
     * @notice Get the Avastar Prime associated with a given Token ID.
     * Does not include the trait replication flags.
     * @param _tokenId the Token ID of the specified Prime
     * @return tokenId the Prime's token ID
     * @return serial the Prime's serial
     * @return traits the Prime's trait hash
     * @return generation the Prime's generation
     * @return series the Prime's series
     * @return gender the Prime's gender
     * @return ranking the Prime's ranking
     */
    function getPrimeByTokenId(uint256 _tokenId)
    external view
    returns (
        uint256 tokenId,
        uint256 serial,
        uint256 traits,
        Generation generation,
        Series series,
        Gender gender,
        uint8 ranking
    ) {
        require(_tokenId < avastars.length);
        Avastar memory avastar = avastars[_tokenId];
        require(avastar.wave ==  Wave.PRIME);
        Prime memory prime = primesByGeneration[uint8(avastar.generation)][avastar.serial];
        return (
            prime.id,
            prime.serial,
            prime.traits,
            prime.generation,
            prime.series,
            prime.gender,
            prime.ranking
        );
    }

    /**
     * @notice Get an Avastar Prime's replication flags by token ID.
     * @param _tokenId the token ID of the specified Prime
     * @return tokenId the Prime's token ID
     * @return replicated the Prime's trait replication flags
     */
    function getPrimeReplicationByTokenId(uint256 _tokenId)
    external view
    returns (
        uint256 tokenId,
        bool[12] memory replicated
    ) {
        require(_tokenId < avastars.length);
        Avastar memory avastar = avastars[_tokenId];
        require(avastar.wave ==  Wave.PRIME);
        Prime memory prime = primesByGeneration[uint8(avastar.generation)][avastar.serial];
        return (
            prime.id,
            prime.replicated
        );
    }

    /**
     * @notice Mint an Avastar Prime
     * Only invokable by minter role, when contract is not paused.
     * If successful, emits a `NewPrime` event.
     * @param _owner the address of the new Avastar's owner
     * @param _traits the new Prime's trait hash
     * @param _generation the new Prime's generation
     * @return _series the new Prime's series
     * @param _gender the new Prime's gender
     * @param _ranking the new Prime's rarity ranking
     * @return tokenId the newly minted Prime's token ID
     * @return serial the newly minted Prime's serial
     */
    function mintPrime(
        address _owner,
        uint256 _traits,
        Generation _generation,
        Series _series,
        Gender _gender,
        uint8 _ranking
    )
    external onlyMinter whenNotPaused
    returns (uint256 tokenId, uint256 serial)
    {
        require(_owner != address(0));
        require(_traits != 0);
        require(isHashUsedByGeneration[uint8(_generation)][_traits] == false);
        require(_ranking > 0 && _ranking <= 100);
        uint16 count = primeCountByGenAndSeries[uint8(_generation)][uint8(_series)];
        if (_series != Series.PROMO) {
            require(count < MAX_PRIMES_PER_SERIES);
        } else {
            require(count < MAX_PROMO_PRIMES_PER_GENERATION);
        }

        // Get Prime Serial and mint Avastar, getting tokenId
        serial = primesByGeneration[uint8(_generation)].length;
        tokenId = mintAvastar(_owner, serial, _traits, _generation, Wave.PRIME);

        // Create and store Prime struct
        bool[12] memory replicated;
        primesByGeneration[uint8(_generation)].push(
            Prime(tokenId, serial, _traits, replicated, _generation, _series, _gender, _ranking)
        );

        // Increment count for given Generation/Series
        primeCountByGenAndSeries[uint8(_generation)][uint8(_series)]++;

        // Send the NewPrime event
        emit NewPrime(tokenId, serial, _generation, _series, _gender, _traits);

        // Return the tokenId, serial
        return (tokenId, serial);
    }

}

// File: contracts/ReplicantFactory.sol

pragma solidity 0.5.14;


/**
 * @title Avastar Replicant Factory
 * @author Cliff Hall
 */
contract ReplicantFactory is PrimeFactory {

    /**
     * @notice Maximum number of Replicants that can be minted
     * in any given generation.
     */
    uint16 public constant MAX_REPLICANTS_PER_GENERATION = 25200;

    /**
     * @notice Event emitted upon the creation of an Avastar Replicant
     * @param id the token ID of the newly minted Replicant
     * @param serial the serial of the Replicant
     * @param generation the generation of the Replicant
     * @param gender the gender of the Replicant
     * @param traits the trait hash of the Replicant
     */
    event NewReplicant(uint256 id, uint256 serial, Generation generation, Gender gender, uint256 traits);

    /**
     * @notice Get the Avastar Replicant metadata associated with a given Generation and Serial
     * @param _generation the generation of the specified Replicant
     * @param _serial the serial of the specified Replicant
     * @return tokenId the Replicant's token ID
     * @return serial the Replicant's serial
     * @return traits the Replicant's trait hash
     * @return generation the Replicant's generation
     * @return gender the Replicant's gender
     * @return ranking the Replicant's ranking
     */
    function getReplicantByGenerationAndSerial(Generation _generation, uint256 _serial)
    external view
    returns (
        uint256 tokenId,
        uint256 serial,
        uint256 traits,
        Generation generation,
        Gender gender,
        uint8 ranking
    ) {
        require(_serial < replicantsByGeneration[uint8(_generation)].length);
        Replicant memory replicant = replicantsByGeneration[uint8(_generation)][_serial];
        return (
            replicant.id,
            replicant.serial,
            replicant.traits,
            replicant.generation,
            replicant.gender,
            replicant.ranking
        );
    }

    /**
     * @notice Get the Avastar Replicant associated with a given Token ID
     * @param _tokenId the token ID of the specified Replicant
     * @return tokenId the Replicant's token ID
     * @return serial the Replicant's serial
     * @return traits the Replicant's trait hash
     * @return generation the Replicant's generation
     * @return gender the Replicant's gender
     * @return ranking the Replicant's ranking
     */
    function getReplicantByTokenId(uint256 _tokenId)
    external view
    returns (
        uint256 tokenId,
        uint256 serial,
        uint256 traits,
        Generation generation,
        Gender gender,
        uint8 ranking
    ) {
        require(_tokenId < avastars.length);
        Avastar memory avastar = avastars[_tokenId];
        require(avastar.wave ==  Wave.REPLICANT);
        Replicant memory replicant = replicantsByGeneration[uint8(avastar.generation)][avastar.serial];
        return (
            replicant.id,
            replicant.serial,
            replicant.traits,
            replicant.generation,
            replicant.gender,
            replicant.ranking
        );
    }

    /**
     * @notice Mint an Avastar Replicant.
     * Only invokable by minter role, when contract is not paused.
     * If successful, emits a `NewReplicant` event.
     * @param _owner the address of the new Avastar's owner
     * @param _traits the new Replicant's trait hash
     * @param _generation the new Replicant's generation
     * @param _gender the new Replicant's gender
     * @param _ranking the new Replicant's rarity ranking
     * @return tokenId the newly minted Replicant's token ID
     * @return serial the newly minted Replicant's serial
     */
    function mintReplicant(
        address _owner,
        uint256 _traits,
        Generation _generation,
        Gender _gender,
        uint8 _ranking
    )
    external onlyMinter whenNotPaused
    returns (uint256 tokenId, uint256 serial)
    {
        require(_traits != 0);
        require(isHashUsedByGeneration[uint8(_generation)][_traits] == false);
        require(_ranking > 0 && _ranking <= 100);
        require(replicantCountByGeneration[uint8(_generation)] < MAX_REPLICANTS_PER_GENERATION);

        // Get Replicant Serial and mint Avastar, getting tokenId
        serial = replicantsByGeneration[uint8(_generation)].length;
        tokenId = mintAvastar(_owner, serial, _traits, _generation, Wave.REPLICANT);

        // Create and store Replicant struct
        replicantsByGeneration[uint8(_generation)].push(
            Replicant(tokenId, serial, _traits, _generation, _gender, _ranking)
        );

        // Increment count for given Generation
        replicantCountByGeneration[uint8(_generation)]++;

        // Send the NewReplicant event
        emit NewReplicant(tokenId, serial, _generation, _gender, _traits);

        // Return the tokenId, serial
        return (tokenId, serial);
    }

}

// File: contracts/IAvastarMetadata.sol

pragma solidity 0.5.14;

/**
 * @title Identification interface for Avastar Metadata generator contract
 * @author Cliff Hall
 * @notice Used by `AvastarTeleporter` contract to validate the address of the contract.
 */
interface IAvastarMetadata {

    /**
     * @notice Acknowledge contract is `AvastarMetadata`
     * @return always true
     */
    function isAvastarMetadata() external pure returns (bool);

    /**
     * @notice Get token URI for a given Avastar Token ID.
     * @param _tokenId the Token ID of a previously minted Avastar Prime or Replicant
     * @return uri the Avastar's off-chain JSON metadata URI
     */
    function tokenURI(uint _tokenId)
    external view
    returns (string memory uri);
}

// File: contracts/AvastarTeleporter.sol

pragma solidity 0.5.14;



/**
 * @title AvastarTeleporter
 * @author Cliff Hall
 * @notice Management of Avastar Primes, Replicants, and Traits
 */
contract AvastarTeleporter is ReplicantFactory {

    /**
     * @notice Event emitted when a handler is approved to manage Trait replication.
     * @param handler the address being approved to Trait replication
     * @param primeIds the array of Avastar Prime tokenIds the handler can use
     */
    event TraitAccessApproved(address indexed handler, uint256[] primeIds);

    /**
     * @notice Event emitted when a handler replicates Traits.
     * @param handler the address marking the Traits as used
     * @param primeId the token id of the Prime supplying the Traits
     * @param used the array of flags representing the Primes resulting Trait usage
     */
    event TraitsUsed(address indexed handler, uint256 primeId, bool[12] used);

    /**
     * @notice Event emitted when AvastarMetadata contract address is set
     * @param contractAddress the address of the new AvastarMetadata contract
     */
    event MetadataContractAddressSet(address contractAddress);

    /**
     * @notice Address of the AvastarMetadata contract
     */
    address private metadataContractAddress;

    /**
     * @notice Acknowledge contract is `AvastarTeleporter`
     * @return always true
     */
    function isAvastarTeleporter() external pure returns (bool) {return true;}

    /**
     * @notice Set the address of the `AvastarMetadata` contract.
     * Only invokable by system admin role, when contract is paused and not upgraded.
     * If successful, emits an `MetadataContractAddressSet` event.
     * @param _address address of AvastarTeleporter contract
     */
    function setMetadataContractAddress(address _address)
    external onlySysAdmin whenPaused whenNotUpgraded
    {
        // Cast the candidate contract to the IAvastarMetadata interface
        IAvastarMetadata candidateContract = IAvastarMetadata(_address);

        // Verify that we have the appropriate address
        require(candidateContract.isAvastarMetadata());

        // Set the contract address
        metadataContractAddress = _address;

        // Emit the event
        emit MetadataContractAddressSet(_address);
    }

    /**
     * @notice Get the current address of the `AvastarMetadata` contract.
     * return contractAddress the address of the `AvastarMetadata` contract
     */
    function getMetadataContractAddress()
    external view
    returns (address contractAddress) {
        return metadataContractAddress;
    }

    /**
     * @notice Get token URI for a given Avastar Token ID.
     * Reverts if given token id is not a valid Avastar Token ID.
     * @param _tokenId the Token ID of a previously minted Avastar Prime or Replicant
     * @return uri the Avastar's off-chain JSON metadata URI
     */
    function tokenURI(uint _tokenId)
    external view
    returns (string memory uri)
    {
        require(_tokenId < avastars.length);
        return IAvastarMetadata(metadataContractAddress).tokenURI(_tokenId);
    }

    /**
     * @notice Approve a handler to manage Trait replication for a set of Avastar Primes.
     * Accepts up to 256 primes for approval per call.
     * Reverts if caller is not owner of all Primes specified.
     * Reverts if no Primes are specified.
     * Reverts if given handler already has approval for all Primes specified.
     * If successful, emits a `TraitAccessApproved` event.
     * @param _handler the address approved for Trait access
     * @param _primeIds the token ids for which to approve the handler
     */
    function approveTraitAccess(address _handler, uint256[] calldata _primeIds)
    external
    {
        require(_primeIds.length > 0 && _primeIds.length <= 256);
        uint256 primeId;
        bool approvedAtLeast1 = false;
        for (uint8 i = 0; i < _primeIds.length; i++) {
            primeId = _primeIds[i];
            require(primeId < avastars.length);
            require(msg.sender == super.ownerOf(primeId), "Must be token owner");
            if (traitHandlerByPrimeTokenId[primeId] != _handler) {
                traitHandlerByPrimeTokenId[primeId] = _handler;
                approvedAtLeast1 = true;
            }
        }
        require(approvedAtLeast1, "No unhandled primes specified");

        // Emit the event
        emit TraitAccessApproved(_handler, _primeIds);
    }

    /**
     * @notice Mark some or all of an Avastar Prime's traits used.
     * Caller must be the token owner OR the approved handler.
     * Caller must send all 12 flags with those to be used set to true, the rest to false.
     * The position of each flag in the `_traitFlags` array corresponds to a Gene, of which Traits are variations.
     * The flag order is: [ SKIN_TONE, HAIR_COLOR, EYE_COLOR, BG_COLOR, BACKDROP, EARS, FACE, NOSE, MOUTH, FACIAL_FEATURE, EYES, HAIR_STYLE ].
     * Reverts if no usable traits are indicated.
     * If successful, emits a `TraitsUsed` event.
     * @param _primeId the token id for the Prime whose Traits are to be used
     * @param _traitFlags an array of no more than 12 booleans representing the Traits to be used
     */
    function useTraits(uint256 _primeId, bool[12] calldata _traitFlags)
    external
    {
        // Make certain token id is valid
        require(_primeId < avastars.length);

        // Make certain caller is token owner OR approved handler
        require(msg.sender == super.ownerOf(_primeId) || msg.sender == traitHandlerByPrimeTokenId[_primeId],
        "Must be token owner or approved handler" );

        // Get the Avastar and make sure it's a Prime
        Avastar memory avastar = avastars[_primeId];
        require(avastar.wave == Wave.PRIME);

        // Get the Prime
        Prime storage prime = primesByGeneration[uint8(avastar.generation)][avastar.serial];

        // Set the flags.
        bool usedAtLeast1;
        for (uint8 i = 0; i < 12; i++) {
            if (_traitFlags.length > i ) {
                if ( !prime.replicated[i] && _traitFlags[i] ) {
                    prime.replicated[i] = true;
                    usedAtLeast1 = true;
                }
            } else {
                break;
            }
        }

        // Revert if no flags changed
        require(usedAtLeast1, "No reusable traits specified");

        // Clear trait handler
        traitHandlerByPrimeTokenId[_primeId] = address(0);

        // Emit the TraitsUsed event
        emit TraitsUsed(msg.sender, _primeId, prime.replicated);
    }

}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"indexed":false,"internalType":"string","name":"artist","type":"string"},{"indexed":false,"internalType":"string","name":"infoURI","type":"string"}],"name":"AttributionSet","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newContract","type":"address"}],"name":"ContractUpgrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"MetadataContractAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"serial","type":"uint256"},{"indexed":false,"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"indexed":false,"internalType":"enum AvastarTypes.Series","name":"series","type":"uint8"},{"indexed":false,"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"traits","type":"uint256"}],"name":"NewPrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"serial","type":"uint256"},{"indexed":false,"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"indexed":false,"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"traits","type":"uint256"}],"name":"NewReplicant","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"indexed":false,"internalType":"enum AvastarTypes.Gene","name":"gene","type":"uint8"},{"indexed":false,"internalType":"enum AvastarTypes.Rarity","name":"rarity","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"variation","type":"uint8"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NewTrait","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"handler","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"primeIds","type":"uint256[]"}],"name":"TraitAccessApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"TraitArtExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"handler","type":"address"},{"indexed":false,"internalType":"uint256","name":"primeId","type":"uint256"},{"indexed":false,"internalType":"bool[12]","name":"used","type":"bool[12]"}],"name":"TraitsUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"MAX_PRIMES_PER_SERIES","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_PROMO_PRIMES_PER_GENERATION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_REPLICANTS_PER_GENERATION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"TOKEN_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"TOKEN_SYMBOL","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_minterAddress","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_ownerAddress","type":"address"}],"name":"addOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_sysAdminAddress","type":"address"}],"name":"addSysAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_handler","type":"address"},{"internalType":"uint256[]","name":"_primeIds","type":"uint256[]"}],"name":"approveTraitAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"attributionByGeneration","outputs":[{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"string","name":"artist","type":"string"},{"internalType":"string","name":"infoURI","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"enum AvastarTypes.Series[]","name":"_series","type":"uint8[]"},{"internalType":"enum AvastarTypes.Gender","name":"_gender","type":"uint8"},{"internalType":"enum AvastarTypes.Gene","name":"_gene","type":"uint8"},{"internalType":"enum AvastarTypes.Rarity","name":"_rarity","type":"uint8"},{"internalType":"uint8","name":"_variation","type":"uint8"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_svg","type":"string"}],"name":"createTrait","outputs":[{"internalType":"uint256","name":"traitId","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_traitId","type":"uint256"},{"internalType":"string","name":"_svg","type":"string"}],"name":"extendTraitArt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"}],"name":"getAttributionByGeneration","outputs":[{"internalType":"string","name":"attribution","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAvastarWaveByTokenId","outputs":[{"internalType":"enum AvastarTypes.Wave","name":"wave","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMetadataContractAddress","outputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"getPrimeByGenerationAndSerial","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"},{"internalType":"uint256","name":"traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"enum AvastarTypes.Series","name":"series","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"internalType":"uint8","name":"ranking","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getPrimeByTokenId","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"},{"internalType":"uint256","name":"traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"enum AvastarTypes.Series","name":"series","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"internalType":"uint8","name":"ranking","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getPrimeReplicationByTokenId","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool[12]","name":"replicated","type":"bool[12]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"getReplicantByGenerationAndSerial","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"},{"internalType":"uint256","name":"traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"internalType":"uint8","name":"ranking","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getReplicantByTokenId","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"},{"internalType":"uint256","name":"traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"internalType":"uint8","name":"ranking","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_traitId","type":"uint256"}],"name":"getTraitArtById","outputs":[{"internalType":"string","name":"art","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"enum AvastarTypes.Gene","name":"_gene","type":"uint8"},{"internalType":"uint8","name":"_variation","type":"uint8"}],"name":"getTraitIdByGenerationGeneAndVariation","outputs":[{"internalType":"uint256","name":"traitId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_traitId","type":"uint256"}],"name":"getTraitInfoById","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"generation","type":"uint8"},{"internalType":"enum AvastarTypes.Series[]","name":"series","type":"uint8[]"},{"internalType":"enum AvastarTypes.Gender","name":"gender","type":"uint8"},{"internalType":"enum AvastarTypes.Gene","name":"gene","type":"uint8"},{"internalType":"enum AvastarTypes.Rarity","name":"rarity","type":"uint8"},{"internalType":"uint8","name":"variation","type":"uint8"},{"internalType":"string","name":"name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_traitId","type":"uint256"}],"name":"getTraitNameById","outputs":[{"internalType":"string","name":"name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isAvastarTeleporter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isHashUsedByGeneration","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"enum AvastarTypes.Series","name":"_series","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"_gender","type":"uint8"},{"internalType":"uint8","name":"_ranking","type":"uint8"}],"name":"mintPrime","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_traits","type":"uint256"},{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"enum AvastarTypes.Gender","name":"_gender","type":"uint8"},{"internalType":"uint8","name":"_ranking","type":"uint8"}],"name":"mintReplicant","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"serial","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"primeCountByGenAndSeries","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"renderAvastar","outputs":[{"internalType":"string","name":"svg","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"replicantCountByGeneration","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum AvastarTypes.Generation","name":"_generation","type":"uint8"},{"internalType":"string","name":"_artist","type":"string"},{"internalType":"string","name":"_infoURI","type":"string"}],"name":"setAttribution","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setMetadataContractAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"stripRoles","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdByGenerationAndHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdByGenerationWaveAndSerial","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"uri","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"}],"name":"traitIdByGenerationGeneAndVariation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"upgradeContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"upgraded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_primeId","type":"uint256"},{"internalType":"bool[12]","name":"_traitFlags","type":"bool[12]"}],"name":"useTraits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60038054600160ff199091161761ff0019169055600760808181526620bb30b9ba30b960c91b60a05261010060405260c09182526620ab20a9aa20a960c91b60e0529081816200005d600033620000ff602090811b62004ecd17901c565b620000786301ffc9a760e01b6001600160e01b036200018c16565b620000936380ac58cd60e01b6001600160e01b036200018c16565b620000ae63780e9d6360e01b6001600160e01b036200018c16565b8151620000c390600d9060208501906200027a565b508051620000d990600e9060208401906200027a565b50620000f5635b5e139f60e01b6001600160e01b036200018c16565b505050506200031f565b6200011482826001600160e01b036200021116565b1562000167576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6001600160e01b03198082161415620001ec576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152600460205260409020805460ff19166001179055565b60006001600160a01b0382166200025a5760405162461bcd60e51b81526004018080602001828103825260228152602001806200632e6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002bd57805160ff1916838001178555620002ed565b82800160010185558215620002ed579182015b82811115620002ed578251825591602001919060010190620002d0565b50620002fb929150620002ff565b5090565b6200031c91905b80821115620002fb576000815560010162000306565b90565b615fff806200032f6000396000f3fe608060405234801561001057600080fd5b50600436106103a35760003560e01c8063786c05af116101e9578063bf3ebb471161010f578063e985e9c5116100ad578063ee454b991161007c578063ee454b9914610f62578063f0a5e6c61461109e578063f66005dd146111e0578063fe6d496a14611206576103a3565b8063e985e9c514610e29578063eaf3a9b914610e57578063eb2c022314610e74578063ed00da2a14610e9a576103a3565b8063c821c971116100e9578063c821c97114610d9a578063c87b56dd14610da2578063c8c4a80a14610dbf578063c98c343414610e0c576103a3565b8063bf3ebb4714610d40578063c28de2cd14610d60578063c4ee86af14610d68576103a3565b8063983b2d5611610187578063ab85937611610156578063ab85937614610b94578063b263c90214610c15578063b622528a14610c3b578063b88d4fde14610c7c576103a3565b8063983b2d5614610b125780639a3b58c914610b38578063a22cb46514610b5e578063a3a8a81614610b8c576103a3565b806391e101b7116101c357806391e101b714610a7c57806394f29abf14610adc578063950699fe14610b0257806395d89b4114610b0a576103a3565b8063786c05af14610939578063808c086b14610a4c5780638456cb5914610a74576103a3565b80632ff640b5116102ce5780634d74d3b41161026c5780636352211e1161023b5780636352211e146108c85780636af04a57146108e55780637065cb48146108ed57806370a0823114610913576103a3565b80634d74d3b4146108085780634f6ccce71461082e5780635a1a7c301461084b5780635c975abb146108c0576103a3565b80634001a267116102a85780634001a26714610713578063413aac781461074557806342842e0e14610775578063480dacfa146107ab576103a3565b80632ff640b5146106c85780633bdafc43146106e55780633f4ba83a1461070b576103a3565b8063169e69bd1161034657806323b872dd1161031557806323b872dd1461063f5780632a22fe41146106755780632a905318146106945780632f745c591461069c576103a3565b8063169e69bd1461057c57806318160ddd146105fa5780631882140014610614578063225ab94e1461061c576103a3565b8063081812fc11610382578063081812fc14610484578063095ea7b3146104a15780630dd4cf9a146104cf57806314d12e0a1461055c576103a3565b80623379d7146103a857806301ffc9a7146103cc57806306fdde0314610407575b600080fd5b6103b0611223565b604080516001600160a01b039092168252519081900360200190f35b6103f3600480360360208110156103e257600080fd5b50356001600160e01b031916611233565b604080519115158252519081900360200190f35b61040f611252565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610449578181015183820152602001610431565b50505050905090810190601f1680156104765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103b06004803603602081101561049a57600080fd5b50356112e8565b6104cd600480360360408110156104b757600080fd5b506001600160a01b03813516906020013561134a565b005b6104ec600480360360208110156104e557600080fd5b5035611472565b6040518088815260200187815260200186815260200185600481111561050e57fe5b60ff16815260200184600581111561052257fe5b60ff16815260200183600281111561053657fe5b60ff1681526020018260ff1660ff16815260200197505050505050505060405180910390f35b61040f6004803603602081101561057257600080fd5b503560ff16611703565b6104cd6004803603604081101561059257600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105bc57600080fd5b8201836020820111156105ce57600080fd5b803590602001918460208302840111600160201b831117156105ef57600080fd5b509092509050611918565b610602611aeb565b60408051918252519081900360200190f35b61040f611af1565b6104cd60048036036101a081101561063357600080fd5b50803590602001611b14565b6104cd6004803603606081101561065557600080fd5b506001600160a01b03813581169160208101359091169060400135611e4b565b61067d611ea7565b6040805161ffff9092168252519081900360200190f35b61040f611ead565b610602600480360360408110156106b257600080fd5b506001600160a01b038135169060200135611ed0565b61040f600480360360208110156106de57600080fd5b5035611f4f565b6104cd600480360360208110156106fb57600080fd5b50356001600160a01b03166120cf565b6104cd612194565b6106026004803603606081101561072957600080fd5b5060ff8135811691602081013582169160409091013516612207565b6106026004803603606081101561075b57600080fd5b5060ff813581169160208101359091169060400135612268565b6104cd6004803603606081101561078b57600080fd5b506001600160a01b0381358116916020810135909116906040013561228b565b6107c8600480360360208110156107c157600080fd5b50356122a6565b604051828152602081018261018080838360005b838110156107f45781810151838201526020016107dc565b505050509050019250505060405180910390f35b6104cd6004803603602081101561081e57600080fd5b50356001600160a01b0316612507565b6106026004803603602081101561084457600080fd5b503561260d565b6104cd6004803603604081101561086157600080fd5b81359190810190604081016020820135600160201b81111561088257600080fd5b82018360208201111561089457600080fd5b803590602001918460018302840111600160201b831117156108b557600080fd5b509092509050612673565b6103f3612881565b6103b0600480360360208110156108de57600080fd5b503561288a565b6103b06128e4565b6104cd6004803603602081101561090357600080fd5b50356001600160a01b03166128f9565b6106026004803603602081101561092957600080fd5b50356001600160a01b0316612941565b6109596004803603602081101561094f57600080fd5b503560ff166129a9565b6040518084600481111561096957fe5b60ff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156109ae578181015183820152602001610996565b50505050905090810190601f1680156109db5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610a0e5781810151838201526020016109f6565b50505050905090810190601f168015610a3b5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b61067d60048036036040811015610a6257600080fd5b5060ff81358116916020013516612ae9565b6104cd612b0a565b610ac3600480360360a0811015610a9257600080fd5b506001600160a01b038135169060208101359060ff6040820135811691606081013582169160809091013516612b6c565b6040805192835260208301919091528051918290030190f35b61060260048036036040811015610af257600080fd5b5060ff8135169060200135612e33565b6103f3612e50565b61040f612e55565b6104cd60048036036020811015610b2857600080fd5b50356001600160a01b0316612eb6565b6104cd60048036036020811015610b4e57600080fd5b50356001600160a01b0316612ef2565b6104cd60048036036040811015610b7457600080fd5b506001600160a01b0381351690602001351515612f2e565b61067d613033565b610bba60048036036040811015610baa57600080fd5b5060ff8135169060200135613039565b60405180878152602001868152602001858152602001846004811115610bdc57fe5b60ff168152602001836002811115610bf057fe5b60ff1681526020018260ff1660ff168152602001965050505050505060405180910390f35b6104ec60048036036040811015610c2b57600080fd5b5060ff813516906020013561317e565b610c5860048036036020811015610c5157600080fd5b5035613362565b60405180826001811115610c6857fe5b60ff16815260200191505060405180910390f35b6104cd60048036036080811015610c9257600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610ccc57600080fd5b820183602082011115610cde57600080fd5b803590602001918460018302840111600160201b83111715610cff57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506133a2945050505050565b61067d60048036036020811015610d5657600080fd5b503560ff16613400565b6103f3613416565b61060260048036036060811015610d7e57600080fd5b5060ff8135811691602081013582169160409091013516613424565b61067d613447565b61040f60048036036020811015610db857600080fd5b503561344c565b610ac3600480360360c0811015610dd557600080fd5b506001600160a01b038135169060208101359060ff60408201358116916060810135821691608082013581169160a001351661359b565b610bba60048036036020811015610e2257600080fd5b503561397f565b6103f360048036036040811015610e3f57600080fd5b506001600160a01b0381358116916020013516613a9b565b61040f60048036036020811015610e6d57600080fd5b5035613ac9565b6104cd60048036036020811015610e8a57600080fd5b50356001600160a01b0316613b89565b6104cd60048036036060811015610eb057600080fd5b60ff8235169190810190604081016020820135600160201b811115610ed457600080fd5b820183602082011115610ee657600080fd5b803590602001918460018302840111600160201b83111715610f0757600080fd5b919390929091602081019035600160201b811115610f2457600080fd5b820183602082011115610f3657600080fd5b803590602001918460018302840111600160201b83111715610f5757600080fd5b509092509050613c43565b6106026004803603610100811015610f7957600080fd5b60ff8235169190810190604081016020820135600160201b811115610f9d57600080fd5b820183602082011115610faf57600080fd5b803590602001918460208302840111600160201b83111715610fd057600080fd5b9193909260ff833581169360208101358216936040820135831693606083013590931692909160a081019060800135600160201b81111561101057600080fd5b82018360208201111561102257600080fd5b803590602001918460018302840111600160201b8311171561104357600080fd5b919390929091602081019035600160201b81111561106057600080fd5b82018360208201111561107257600080fd5b803590602001918460018302840111600160201b8311171561109357600080fd5b509092509050613e82565b6110bb600480360360208110156110b457600080fd5b5035614299565b604051808981526020018860048111156110d157fe5b60ff168152602001806020018760028111156110e957fe5b60ff16815260200186600b8111156110fd57fe5b60ff16815260200185600481111561111157fe5b60ff1681526020018460ff1660ff16815260200180602001838103835289818151815260200191508051906020019060200280838360005b83811015611161578181015183820152602001611149565b50505050905001838103825284818151815260200191508051906020019080838360005b8381101561119d578181015183820152602001611185565b50505050905090810190601f1680156111ca5780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390f35b6103f3600480360360408110156111f657600080fd5b5060ff81351690602001356145aa565b61040f6004803603602081101561121c57600080fd5b50356145ca565b601c546001600160a01b03165b90565b6001600160e01b03191660009081526004602052604090205460ff1690565b600d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112de5780601f106112b3576101008083540402835291602001916112de565b820191906000526020600020905b8154815290600101906020018083116112c157829003601f168201915b5050505050905090565b60006112f3826148a8565b61132e5760405162461bcd60e51b815260040180806020018281038252602c815260200180615eaf602c913960400191505060405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006113558261288a565b9050806001600160a01b0316836001600160a01b031614156113a85760405162461bcd60e51b8152600401808060200182810382526021815260200180615f266021913960400191505060405180910390fd5b806001600160a01b03166113ba6148c5565b6001600160a01b031614806113db57506113db816113d66148c5565b613a9b565b6114165760405162461bcd60e51b8152600401808060200182810382526038815260200180615e036038913960400191505060405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000806000806000806000601080549050881061148e57600080fd5b6114966159a7565b601089815481106114a357fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff1660048111156114f857fe5b600481111561150357fe5b81526020016003820160019054906101000a900460ff16600181111561152557fe5b600181111561153057fe5b905250905060008160800151600181111561154757fe5b1461155157600080fd5b6115596159e0565b601260008360600151600481111561156d57fe5b60ff1660ff16815260200190815260200160002082602001518154811061159057fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015611624576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116115f35790505b505050918352505060048281015460209092019160ff169081111561164557fe5b600481111561165057fe5b81526020016004820160019054906101000a900460ff16600581111561167257fe5b600581111561167d57fe5b81526020016004820160029054906101000a900460ff16600281111561169f57fe5b60028111156116aa57fe5b81526004919091015460ff6301000000909104166020918201528151908201516040830151608084015160a085015160c086015160e090960151949e50929c50909a509850965090945092505050919395979092949650565b606061170d615a2c565b6014600084600481111561171d57fe5b60ff908116825260208201929092526040908101600020815160608101909252805491929091839116600481111561175157fe5b600481111561175c57fe5b8152602001600182018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117f95780601f106117ce576101008083540402835291602001916117f9565b820191906000526020600020905b8154815290600101906020018083116117dc57829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801561188b5780601f106118605761010080835404028352916020019161188b565b820191906000526020600020905b81548152906001019060200180831161186e57829003601f168201915b50505050508152505090506000816020015151116118a857600080fd5b6118b68282602001516148c9565b91506118dc8260405180604001604052806002815260200161040560f31b8152506148c9565b91506118ec8282604001516148c9565b915061191182604051806040016040528060018152602001602960f81b8152506148c9565b9392505050565b801580159061192957506101008111155b61193257600080fd5b600080805b60ff8116841115611a245784848260ff1681811061195157fe5b905060200201359250601080549050831061196b57600080fd5b6119748361288a565b6001600160a01b0316336001600160a01b0316146119cf576040805162461bcd60e51b815260206004820152601360248201527226bab9ba103132903a37b5b2b71037bbb732b960691b604482015290519081900360640190fd5b6000838152601560205260409020546001600160a01b03878116911614611a1c57600083815260156020526040902080546001600160a01b0319166001600160a01b038816179055600191505b600101611937565b5080611a77576040805162461bcd60e51b815260206004820152601d60248201527f4e6f20756e68616e646c6564207072696d657320737065636966696564000000604482015290519081900360640190fd5b846001600160a01b03167f571f01a38e9f9580bf7e012e93cbf1db0f5741a6260c70ca67325de02fec78f3858560405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a25050505050565b600b5490565b6040518060400160405280600781526020016620bb30b9ba30b960c91b81525081565b6010548210611b2257600080fd5b611b2b8261288a565b6001600160a01b0316336001600160a01b03161480611b6057506000828152601560205260409020546001600160a01b031633145b611b9b5760405162461bcd60e51b8152600401808060200182810382526027815260200180615fa46027913960400191505060405180910390fd5b611ba36159a7565b60108381548110611bb057fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115611c0557fe5b6004811115611c1057fe5b81526020016003820160019054906101000a900460ff166001811115611c3257fe5b6001811115611c3d57fe5b9052509050600081608001516001811115611c5457fe5b14611c5e57600080fd5b60006012600083606001516004811115611c7457fe5b60ff1660ff168152602001908152602001600020826020015181548110611c9757fe5b6000918252602082206005909102019150805b600c8160ff161015611d58578060ff16600c1115611d4b57826003018160ff16600c8110611cd457fe5b602081049091015460ff601f9092166101000a900416158015611d095750848160ff16600c8110611d0157fe5b602002013515155b15611d46576001836003018260ff16600c8110611d2257fe5b602091828204019190066101000a81548160ff021916908315150217905550600191505b611d50565b611d58565b600101611caa565b5080611dab576040805162461bcd60e51b815260206004820152601c60248201527f4e6f207265757361626c65207472616974732073706563696669656400000000604482015290519081900360640190fd5b600085815260156020908152604080832080546001600160a01b03191690555187815233927fbbb2a94727e40c0fd33d28dc12b7474244c1d2add15fe036b15a550b79905192928992600388019290916101a0830191849184015b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411611e0657905050509250505060405180910390a25050505050565b611e5c611e566148c5565b82614984565b611e975760405162461bcd60e51b8152600401808060200182810382526031815260200180615f476031913960400191505060405180910390fd5b611ea2838383614a20565b505050565b61138881565b6040518060400160405280600781526020016620ab20a9aa20a960c91b81525081565b6000611edb83612941565b8210611f185760405162461bcd60e51b815260040180806020018281038252602b815260200180615cbe602b913960400191505060405180910390fd5b6001600160a01b0383166000908152600960205260409020805483908110611f3c57fe5b9060005260206000200154905092915050565b6010546060908210611f6057600080fd5b611f686159a7565b60108381548110611f7557fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115611fca57fe5b6004811115611fd557fe5b81526020016003820160019054906101000a900460ff166001811115611ff757fe5b600181111561200257fe5b90525090506000808260800151600181111561201a57fe5b1461206d57601360008360600151600481111561203357fe5b60ff1660ff16815260200190815260200160002082602001518154811061205657fe5b9060005260206000209060040201600201546120b7565b601260008360600151600481111561208157fe5b60ff1660ff1681526020019081526020016000208260200151815481106120a457fe5b9060005260206000209060050201600201545b90506120c7826060015182614a3f565b949350505050565b6120e060023363ffffffff614dff16565b6120e957600080fd5b336001600160a01b03821614156120ff57600080fd5b6000612111818363ffffffff614dff16565b1561212b5761212760008363ffffffff614e6616565b5060015b61213c60018363ffffffff614dff16565b156121565761215260018363ffffffff614e6616565b5060015b61216760028363ffffffff614dff16565b156121815761217d60028363ffffffff614e6616565b5060015b60018115151461219057600080fd5b5050565b6121a560003363ffffffff614dff16565b6121ae57600080fd5b60035460ff166121bd57600080fd5b600354610100900460ff16156121d257600080fd5b6003805460ff191690556040517f0e5e3b3fb504c22cf5c42fa07d521225937514c654007e1f12646f89768d6f9490600090a1565b6000601b600085600481111561221957fe5b60ff1660ff168152602001908152602001600020600084600b81111561223b57fe5b60ff9081168252602080830193909352604091820160009081209186168152925290205490509392505050565b601a60209081526000938452604080852082529284528284209052825290205481565b611ea2838383604051806020016040528060008152506133a2565b60006122b0615a4e565b60105483106122be57600080fd5b6122c66159a7565b601084815481106122d357fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff16600481111561232857fe5b600481111561233357fe5b81526020016003820160019054906101000a900460ff16600181111561235557fe5b600181111561236057fe5b905250905060008160800151600181111561237757fe5b1461238157600080fd5b6123896159e0565b601260008360600151600481111561239d57fe5b60ff1660ff1681526020019081526020016000208260200151815481106123c057fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015612454576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116124235790505b505050918352505060048281015460209092019160ff169081111561247557fe5b600481111561248057fe5b81526020016004820160019054906101000a900460ff1660058111156124a257fe5b60058111156124ad57fe5b81526020016004820160029054906101000a900460ff1660028111156124cf57fe5b60028111156124da57fe5b8152600491909101546301000000900460ff16602090910152805160609091015190969095509350505050565b61251860003363ffffffff614dff16565b61252157600080fd5b60035460ff1661253057600080fd5b600354610100900460ff161561254557600080fd5b6000819050806001600160a01b031663e486b6816040518163ffffffff1660e01b815260040160206040518083038186803b15801561258357600080fd5b505afa158015612597573d6000803e3d6000fd5b505050506040513d60208110156125ad57600080fd5b50516125b857600080fd5b601c80546001600160a01b0384166001600160a01b0319909116811790915560408051918252517f13151dbeeb461e21144c44310d3f712709198f403d9e3833f08601071704deb19181900360200190a15050565b6000612617611aeb565b82106126545760405162461bcd60e51b815260040180806020018281038252602c815260200180615f78602c913960400191505060405180910390fd5b600b828154811061266157fe5b90600052602060002001549050919050565b61268460003363ffffffff614dff16565b61268d57600080fd5b60035460ff161561269d57600080fd5b601183815481106126aa57fe5b6000918252602082206001600590920201015460ff16906012908260048111156126d057fe5b60ff1681526020810191909152604001600020541580156127125750601360008260048111156126fc57fe5b60ff168152602081019190915260400160002054155b61271b57600080fd5b601154841061272957600080fd5b60606128126011868154811061273b57fe5b6000918252602091829020600460059092020101805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156127d15780601f106127a6576101008083540402835291602001916127d1565b820191906000526020600020905b8154815290600101906020018083116127b457829003601f168201915b505050505085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506148c992505050565b9050806011868154811061282257fe5b90600052602060002090600502016004019080519060200190612846929190615a6d565b506040805186815290517f1ac2a8040df3df1374b56e8c1a1d073cc9bba1d7d18e7d59dd86be04351e97cc9181900360200190a15050505050565b60035460ff1681565b6000818152600560205260408120546001600160a01b0316806128de5760405162461bcd60e51b8152600401808060200182810382526029815260200180615e656029913960400191505060405180910390fd5b92915050565b6003546201000090046001600160a01b031681565b61290a60003363ffffffff614dff16565b61291357600080fd5b61292460028263ffffffff614ecd16565b61293560028263ffffffff614dff16565b61293e57600080fd5b50565b60006001600160a01b0382166129885760405162461bcd60e51b815260040180806020018281038252602a815260200180615e3b602a913960400191505060405180910390fd5b6001600160a01b03821660009081526007602052604090206128de90614f4e565b6014602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff909216949293909290830182828015612a4d5780601f10612a2257610100808354040283529160200191612a4d565b820191906000526020600020905b815481529060010190602001808311612a3057829003601f168201915b50505060028085018054604080516020601f6000196101006001871615020190941695909504928301859004850281018501909152818152959695945090925090830182828015612adf5780601f10612ab457610100808354040283529160200191612adf565b820191906000526020600020905b815481529060010190602001808311612ac257829003601f168201915b5050505050905083565b601860209081526000928352604080842090915290825290205461ffff1681565b612b1b60003363ffffffff614dff16565b612b2457600080fd5b60035460ff1615612b3457600080fd5b6003805460ff191660011790556040517fab35696f06e428ebc5ceba8cd17f8fed287baf43440206d1943af1ee53e6d26790600090a1565b600080612b8060013363ffffffff614dff16565b612b8957600080fd5b60035460ff1615612b9957600080fd5b85612ba357600080fd5b60166000866004811115612bb357fe5b60ff9081168252602080830193909352604091820160009081208a82529093529120541615612be157600080fd5b60008360ff16118015612bf8575060648360ff1611155b612c0157600080fd5b61627060196000876004811115612c1457fe5b60ff16815260208101919091526040016000205461ffff1610612c3657600080fd5b60136000866004811115612c4657fe5b60ff1681526020810191909152604001600020549050612c6a878288886001614f52565b915060136000866004811115612c7c57fe5b60ff1660ff1681526020019081526020016000206040518060c00160405280848152602001838152602001888152602001876004811115612cb957fe5b8152602001866002811115612cca57fe5b815260ff8616602091820152825460018181018086556000958652948390208451600493840290910190815592840151838201556040840151600284015560608401516003840180549193909260ff1990921691908490811115612d2a57fe5b0217905550608082015160038201805461ff001916610100836002811115612d4e57fe5b021790555060a08201518160030160026101000a81548160ff021916908360ff16021790555050505060196000866004811115612d8757fe5b60ff1681526020808201929092526040908101600020805461ffff8082166001011661ffff1990911617905580518481529182018390527fd6e5b8cb521b8e2deca8334964545247f158fa2e98a568e1e11671dd4697bf209184918491899189918c918101846004811115612df857fe5b60ff168152602001836002811115612e0c57fe5b60ff1681526020018281526020019550505050505060405180910390a19550959350505050565b601760209081526000928352604080842090915290825290205481565b600190565b600e8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112de5780601f106112b3576101008083540402835291602001916112de565b612ec760003363ffffffff614dff16565b612ed057600080fd5b612ee160018263ffffffff614ecd16565b61293560018263ffffffff614dff16565b612f0360003363ffffffff614dff16565b612f0c57600080fd5b612f1d60008263ffffffff614ecd16565b61293560008263ffffffff614dff16565b612f366148c5565b6001600160a01b0316826001600160a01b03161415612f9c576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060086000612fa96148c5565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155612fed6148c5565b60408051841515815290516001600160a01b0392909216917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319181900360200190a35050565b61627081565b6000806000806000806013600089600481111561305257fe5b60ff168152602081019190915260400160002054871061307157600080fd5b613079615aeb565b601360008a600481111561308957fe5b60ff1660ff16815260200190815260200160002088815481106130a857fe5b90600052602060002090600402016040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff1660048111156130fd57fe5b600481111561310857fe5b81526020016003820160019054906101000a900460ff16600281111561312a57fe5b600281111561313557fe5b81526003919091015462010000900460ff1660209182015281519082015160408301516060840151608085015160a090950151939e929d50909b50995091975095509350505050565b6000806000806000806000601260008a600481111561319957fe5b60ff16815260208101919091526040016000205488106131b857600080fd5b6131c06159e0565b601260008b60048111156131d057fe5b60ff1660ff16815260200190815260200160002089815481106131ef57fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015613283576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116132525790505b505050918352505060048281015460209092019160ff16908111156132a457fe5b60048111156132af57fe5b81526020016004820160019054906101000a900460ff1660058111156132d157fe5b60058111156132dc57fe5b81526020016004820160029054906101000a900460ff1660028111156132fe57fe5b600281111561330957fe5b81526004919091015460ff6301000000909104166020918201528151908201516040830151608084015160a085015160c086015160e090960151949d50929b509099509750955090935091505092959891949750929550565b601054600090821061337357600080fd5b6010828154811061338057fe5b6000918252602090912060049091020160030154610100900460ff1692915050565b6133b36133ad6148c5565b83614984565b6133ee5760405162461bcd60e51b8152600401808060200182810382526031815260200180615f476031913960400191505060405180910390fd5b6133fa8484848461528a565b50505050565b60196020526000908152604090205461ffff1681565b600354610100900460ff1681565b601b60209081526000938452604080852082529284528284209052825290205481565b60c881565b601054606090821061345d57600080fd5b601c546040805163c87b56dd60e01b81526004810185905290516001600160a01b039092169163c87b56dd91602480820192600092909190829003018186803b1580156134a957600080fd5b505afa1580156134bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156134e657600080fd5b8101908080516040519392919084600160201b82111561350557600080fd5b90830190602082018581111561351a57600080fd5b8251600160201b81118282018810171561353357600080fd5b82525081516020918201929091019080838360005b83811015613560578181015183820152602001613548565b50505050905090810190601f16801561358d5780820380516001836020036101000a031916815260200191505b506040525050509050919050565b6000806135af60013363ffffffff614dff16565b6135b857600080fd5b60035460ff16156135c857600080fd5b6001600160a01b0388166135db57600080fd5b866135e557600080fd5b601660008760048111156135f557fe5b60ff9081168252602080830193909352604091820160009081208b8252909352912054161561362357600080fd5b60008360ff1611801561363a575060648360ff1611155b61364357600080fd5b60006018600088600481111561365557fe5b60ff1660ff168152602001908152602001600020600087600581111561367757fe5b60ff168152602081019190915260400160009081205461ffff16915086600581111561369f57fe5b146136bb5761138861ffff8216106136b657600080fd5b6136cc565b60c861ffff8216106136cc57600080fd5b601260008860048111156136dc57fe5b60ff1660ff16815260200190815260200160002080549050915061370489838a8a6000614f52565b925061370e615a4e565b6012600089600481111561371e57fe5b60ff1660ff1681526020019081526020016000206040518061010001604052808681526020018581526020018b81526020018381526020018a600481111561376257fe5b815260200189600581111561377357fe5b815260200188600281111561378457fe5b815260ff881660209182015282546001818101808655600095865294839020845160059093020191825591830151918101919091556040820151600282015560608201516137d8906003830190600c615b18565b5060808201518160040160006101000a81548160ff021916908360048111156137fd57fe5b021790555060a082015160048201805461ff00191661010083600581111561382157fe5b021790555060c082015160048201805462ff000019166201000083600281111561384757fe5b021790555060e08201518160040160036101000a81548160ff021916908360ff1602179055505050506018600089600481111561388057fe5b60ff1660ff16815260200190815260200160002060008860058111156138a257fe5b60ff1660ff168152602001908152602001600020600081819054906101000a900461ffff168092919060010191906101000a81548161ffff021916908361ffff160217905550507fcda0c43783a712d26fef88c79742e07db82ff51962220e36f70cb852dcd0c4ef84848a8a8a8e6040518087815260200186815260200185600481111561392c57fe5b60ff16815260200184600581111561394057fe5b60ff16815260200183600281111561395457fe5b60ff168152602001828152602001965050505050505060405180910390a15050965096945050505050565b600080600080600080601080549050871061399957600080fd5b6139a16159a7565b601088815481106139ae57fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115613a0357fe5b6004811115613a0e57fe5b81526020016003820160019054906101000a900460ff166001811115613a3057fe5b6001811115613a3b57fe5b9052509050600181608001516001811115613a5257fe5b14613a5c57600080fd5b613a64615aeb565b6013600083606001516004811115613a7857fe5b60ff1660ff1681526020019081526020016000208260200151815481106130a857fe5b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205460ff1690565b6011546060908210613ada57600080fd5b60118281548110613ae757fe5b6000918252602091829020600360059092020101805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015613b7d5780601f10613b5257610100808354040283529160200191613b7d565b820191906000526020600020905b815481529060010190602001808311613b6057829003601f168201915b50505050509050919050565b613b9a60003363ffffffff614dff16565b613ba357600080fd5b60035460ff16613bb257600080fd5b600354610100900460ff1615613bc757600080fd5b6001600160a01b038116613bda57600080fd5b6003805461010061ff00199091161762010000600160b01b031916620100006001600160a01b0384169081029190911790915560408051918252517f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa446199305916020908290030190a150565b613c5460003363ffffffff614dff16565b613c5d57600080fd5b8460126000826004811115613c6e57fe5b60ff168152602081019190915260400160002054158015613cb0575060136000826004811115613c9a57fe5b60ff168152602081019190915260400160002054155b613cb957600080fd5b8315801590613cc757508115155b613cd057600080fd5b6040518060600160405280876004811115613ce757fe5b815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f87018190048102820181019092528581529181019190869086908190840183828082843760009201829052509390945250601492508990506004811115613d7057fe5b60ff168152602081019190915260400160002081518154829060ff19166001836004811115613d9b57fe5b02179055506020828101518051613db89260018501920190615a6d565b5060408201518051613dd4916002840191602090910190615a6d565b509050507fae7bd40c57594fc1eada1cdb57956d2e028bf0e14959f3ff73b31e884bde0563868686868660405180866004811115613e0e57fe5b60ff16815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a1505050505050565b6000613e94813363ffffffff614dff16565b613e9d57600080fd5b60035460ff1615613ead57600080fd5b8b60126000826004811115613ebe57fe5b60ff168152602081019190915260400160002054158015613f00575060136000826004811115613eea57fe5b60ff168152602081019190915260400160002054155b613f0957600080fd5b8a613f1357600080fd5b84613f1d57600080fd5b82613f2757600080fd5b601180549050915060116040518061012001604052808481526020018f6004811115613f4f57fe5b81526020018c6002811115613f6057fe5b81526020018b600b811115613f7157fe5b81526020018a6004811115613f8257fe5b81526020018960ff1681526020018e8e80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250604080516020601f8b0181900481028201810190925289815291810191908a908a9081908401838280828437600092019190915250505090825250604080516020601f89018190048102820181019092528781529181019190889088908190840183828082843760009201829052509390945250508354600181810180875595835260209283902085516005909302019182559184015181830180549294509092909160ff19169083600481111561407a57fe5b0217905550604082015160018201805461ff00191661010083600281111561409e57fe5b0217905550606082015160018201805462ff000019166201000083600b8111156140c457fe5b0217905550608082015160018201805463ff000000191663010000008360048111156140ec57fe5b021790555060a082015160018201805460ff909216600160201b0264ff000000001990921691909117905560c08201518051614132916002840191602090910190615ba6565b5060e0820151805161414e916003840191602090910190615a6d565b50610100820151805161416b916004840191602090910190615a6d565b5050505081601b60008f600481111561418057fe5b60ff1660ff16815260200190815260200160002060008b600b8111156141a257fe5b60ff1660ff16815260200190815260200160002060008960ff1660ff168152602001908152602001600020819055507fafe2beb8771ed6e9287abf691a85f85c4df73ce22e7c53d4b01d755fddba0352828e8b8b8b8b8b6040518088815260200187600481111561420f57fe5b60ff16815260200186600b81111561422357fe5b60ff16815260200185600481111561423757fe5b60ff1681526020018460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039a509098505050505050505050a1509b9a5050505050505050505050565b6000806060600080600080606060118054905089106142b757600080fd5b6142bf615c15565b60118a815481106142cc57fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff16600481111561430e57fe5b600481111561431957fe5b81526020016001820160019054906101000a900460ff16600281111561433b57fe5b600281111561434657fe5b81526020016001820160029054906101000a900460ff16600b81111561436857fe5b600b81111561437357fe5b81526020016001820160039054906101000a900460ff16600481111561439557fe5b60048111156143a057fe5b81526001820154600160201b900460ff16602080830191909152600283018054604080518285028101850182528281529401939283018282801561442d57602002820191906000526020600020906000905b82829054906101000a900460ff16600581111561440b57fe5b8152602060019283018181049485019490930390920291018084116143f25790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156144c15780601f10614496576101008083540402835291602001916144c1565b820191906000526020600020905b8154815290600101906020018083116144a457829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156145555780601f1061452a57610100808354040283529160200191614555565b820191906000526020600020905b81548152906001019060200180831161453857829003601f168201915b5050505050815250509050806000015181602001518260c001518360400151846060015185608001518660a001518760e001518595508090509850985098509850985098509850985050919395975091939597565b601660209081526000928352604080842090915290825290205460ff1681565b60606145dd60003363ffffffff614dff16565b6145e657600080fd5b60115482106145f457600080fd5b6145fc615c15565b6011838154811061460957fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff16600481111561464b57fe5b600481111561465657fe5b81526020016001820160019054906101000a900460ff16600281111561467857fe5b600281111561468357fe5b81526020016001820160029054906101000a900460ff16600b8111156146a557fe5b600b8111156146b057fe5b81526020016001820160039054906101000a900460ff1660048111156146d257fe5b60048111156146dd57fe5b81526001820154600160201b900460ff16602080830191909152600283018054604080518285028101850182528281529401939283018282801561476a57602002820191906000526020600020906000905b82829054906101000a900460ff16600581111561474857fe5b81526020600192830181810494850194909303909202910180841161472f5790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156147fe5780601f106147d3576101008083540402835291602001916147fe565b820191906000526020600020905b8154815290600101906020018083116147e157829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156148925780601f1061486757610100808354040283529160200191614892565b820191906000526020600020905b81548152906001019060200180831161487557829003601f168201915b5050509190925250505061010001519392505050565b6000908152600560205260409020546001600160a01b0316151590565b3390565b606082826040516020018083805190602001908083835b602083106148ff5780518252601f1990920191602091820191016148e0565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106149475780518252601f199092019160209182019101614928565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052905092915050565b600061498f826148a8565b6149ca5760405162461bcd60e51b815260040180806020018281038252602c815260200180615dd7602c913960400191505060405180910390fd5b60006149d58361288a565b9050806001600160a01b0316846001600160a01b03161480614a105750836001600160a01b0316614a05846112e8565b6001600160a01b0316145b806120c757506120c78185613a9b565b614a2b8383836152dc565b614a358382615420565b611ea28282615515565b606060008211614a4e57600080fd5b60606040518060c0016040528060988152602001615d1b60989139905061010060ff600080808080614a7e615c15565b60005b600b60ff821611614dc65760ff8116890a88810297508c8816965094508515614dbe5760008160ff1611614ab55785614ac0565b848681614abe57fe5b045b93508315614dbe57601b60008e6004811115614ad857fe5b60ff9081168252602080830193909352604091820160009081208583168252845282812091881681529252902054601180549194509084908110614b1857fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff166004811115614b5a57fe5b6004811115614b6557fe5b81526020016001820160019054906101000a900460ff166002811115614b8757fe5b6002811115614b9257fe5b81526020016001820160029054906101000a900460ff16600b811115614bb457fe5b600b811115614bbf57fe5b81526020016001820160039054906101000a900460ff166004811115614be157fe5b6004811115614bec57fe5b81526001820154600160201b900460ff166020808301919091526002830180546040805182850281018501825282815294019392830182828015614c7957602002820191906000526020600020906000905b82829054906101000a900460ff166005811115614c5757fe5b815260206001928301818104948501949093039092029101808411614c3e5790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152938201939291830182828015614d0d5780601f10614ce257610100808354040283529160200191614d0d565b820191906000526020600020905b815481529060010190602001808311614cf057829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152938201939291830182828015614da15780601f10614d7657610100808354040283529160200191614da1565b820191906000526020600020905b815481529060010190602001808311614d8457829003601f168201915b5050505050815250509150614dbb8a8361010001516148c9565b99505b600101614a81565b50614def89604051806040016040528060068152602001651e17b9bb339f60d11b8152506148c9565b9c9b505050505050505050505050565b60006001600160a01b038216614e465760405162461bcd60e51b8152600401808060200182810382526022815260200180615edb6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b614e708282614dff565b614eab5760405162461bcd60e51b8152600401808060200182810382526021815260200180615e8e6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b614ed78282614dff565b15614f29576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b5490565b60035460009060ff1615614f6557600080fd5b601a6000846004811115614f7557fe5b60ff1660ff1681526020019081526020016000206000836001811115614f9757fe5b60ff1681526020808201929092526040908101600090812088825290925290205415614fc257600080fd5b6000826001811115614fd057fe5b141561500a5760126000846004811115614fe657fe5b60ff168152602081019190915260400160002054851461500557600080fd5b615039565b6013600084600481111561501a57fe5b60ff168152602081019190915260400160002054851461503957600080fd5b506010546150456159a7565b6040518060a0016040528083815260200187815260200186815260200185600481111561506e57fe5b815260200184600181111561507f57fe5b9052601080546001818101808455600093909352835160049283027f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672810191825560208601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67382015560408601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67482015560608601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6759091018054969750949587959294919360ff1990911691849081111561515a57fe5b0217905550608082015160038201805461ff00191661010083600181111561517e57fe5b02179055505050506001601660008360600151600481111561519c57fe5b60ff168152602080820192909252604090810160009081208583015182529092528120805460ff19169215159290921790915581516060830151909160179160048111156151e657fe5b60ff1660ff168152602001908152602001600020600083604001518152602001908152602001600020819055508060000151601a60008360600151600481111561522c57fe5b60ff1660ff16815260200190815260200160002060008360800151600181111561525257fe5b60ff168152602080820192909252604090810160009081208584015182529092529020556152808783615553565b5095945050505050565b615295848484614a20565b6152a184848484615570565b6133fa5760405162461bcd60e51b8152600401808060200182810382526032815260200180615ce96032913960400191505060405180910390fd5b826001600160a01b03166152ef8261288a565b6001600160a01b0316146153345760405162461bcd60e51b8152600401808060200182810382526029815260200180615efd6029913960400191505060405180910390fd5b6001600160a01b0382166153795760405162461bcd60e51b8152600401808060200182810382526024815260200180615db36024913960400191505060405180910390fd5b615382816156c7565b6001600160a01b03831660009081526007602052604090206153a390615702565b6001600160a01b03821660009081526007602052604090206153c490615719565b60008181526005602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b03821660009081526009602052604081205461544a90600163ffffffff61572216565b6000838152600a60205260409020549091508082146154e5576001600160a01b038416600090815260096020526040812080548490811061548757fe5b906000526020600020015490508060096000876001600160a01b03166001600160a01b0316815260200190815260200160002083815481106154c557fe5b6000918252602080832090910192909255918252600a9052604090208190555b6001600160a01b038416600090815260096020526040902080549061550e906000198301615c65565b5050505050565b6001600160a01b0390911660009081526009602081815260408084208054868652600a84529185208290559282526001810183559183529091200155565b61555d8282615764565b6155678282615515565b61219081615895565b6000615584846001600160a01b03166158d9565b615590575060016120c7565b6000846001600160a01b031663150b7a026155a96148c5565b8887876040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561562e578181015183820152602001615616565b50505050905090810190601f16801561565b5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561567d57600080fd5b505af1158015615691573d6000803e3d6000fd5b505050506040513d60208110156156a757600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b6000818152600660205260409020546001600160a01b03161561293e57600090815260066020526040902080546001600160a01b0319169055565b805461571590600163ffffffff61572216565b9055565b80546001019055565b600061191183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615910565b6001600160a01b0382166157bf576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6157c8816148a8565b1561581a576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b0319166001600160a01b03871690811790915583526007909152902061585990615719565b60405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906120c75750141592915050565b6000818484111561599f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561596457818101518382015260200161594c565b50505050905090810190601f1680156159915780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6040518060a00160405280600081526020016000815260200160008152602001600060048111156159d457fe5b81526020016000905290565b604051806101000160405280600081526020016000815260200160008152602001615a09615a4e565b81526020016000815260200160005b815260200160008152600060209091015290565b6040805160608101909152806000815260200160608152602001606081525090565b604051806101800160405280600c906020820280388339509192915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615aae57805160ff1916838001178555615adb565b82800160010185558215615adb579182015b82811115615adb578251825591602001919060010190615ac0565b50615ae7929150615c85565b5090565b6040518060c0016040528060008152602001600081526020016000815260200160006004811115615a1857fe5b600183019183908215615b9a5791602002820160005b83821115615b6b57835183826101000a81548160ff0219169083151502179055509260200192600101602081600001049283019260010302615b2e565b8015615b985782816101000a81549060ff0219169055600101602081600001049283019260010302615b6b565b505b50615ae7929150615c9f565b82805482825590600052602060002090601f01602090048101928215615b9a5791602002820160005b83821115615b6b57835183826101000a81548160ff02191690836005811115615bf457fe5b02179055509260200192600101602081600001049283019260010302615bcf565b604080516101208101909152600080825260208201908152602001600081526020016000815260200160008152602001600060ff1681526020016060815260200160608152602001606081525090565b815481835581811115611ea257600083815260209020611ea29181019083015b61123091905b80821115615ae75760008155600101615c8b565b61123091905b80821115615ae757805460ff19168155600101615ca556fe455243373231456e756d657261626c653a206f776e657220696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465723c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b222076657273696f6e3d22312e3122206865696768743d22313030307078222077696474683d22313030307078222076696577426f783d2230203020313030302031303030223e4552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c654552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e526f6c65733a206163636f756e7420697320746865207a65726f20616464726573734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564455243373231456e756d657261626c653a20676c6f62616c20696e646578206f7574206f6620626f756e64734d75737420626520746f6b656e206f776e6572206f7220617070726f7665642068616e646c6572a265627a7a7231582058dc70ca79f03c655381e9b8ffb65b62e19238f259a0093e34ed6dde4d524ae864736f6c634300050e0032526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103a35760003560e01c8063786c05af116101e9578063bf3ebb471161010f578063e985e9c5116100ad578063ee454b991161007c578063ee454b9914610f62578063f0a5e6c61461109e578063f66005dd146111e0578063fe6d496a14611206576103a3565b8063e985e9c514610e29578063eaf3a9b914610e57578063eb2c022314610e74578063ed00da2a14610e9a576103a3565b8063c821c971116100e9578063c821c97114610d9a578063c87b56dd14610da2578063c8c4a80a14610dbf578063c98c343414610e0c576103a3565b8063bf3ebb4714610d40578063c28de2cd14610d60578063c4ee86af14610d68576103a3565b8063983b2d5611610187578063ab85937611610156578063ab85937614610b94578063b263c90214610c15578063b622528a14610c3b578063b88d4fde14610c7c576103a3565b8063983b2d5614610b125780639a3b58c914610b38578063a22cb46514610b5e578063a3a8a81614610b8c576103a3565b806391e101b7116101c357806391e101b714610a7c57806394f29abf14610adc578063950699fe14610b0257806395d89b4114610b0a576103a3565b8063786c05af14610939578063808c086b14610a4c5780638456cb5914610a74576103a3565b80632ff640b5116102ce5780634d74d3b41161026c5780636352211e1161023b5780636352211e146108c85780636af04a57146108e55780637065cb48146108ed57806370a0823114610913576103a3565b80634d74d3b4146108085780634f6ccce71461082e5780635a1a7c301461084b5780635c975abb146108c0576103a3565b80634001a267116102a85780634001a26714610713578063413aac781461074557806342842e0e14610775578063480dacfa146107ab576103a3565b80632ff640b5146106c85780633bdafc43146106e55780633f4ba83a1461070b576103a3565b8063169e69bd1161034657806323b872dd1161031557806323b872dd1461063f5780632a22fe41146106755780632a905318146106945780632f745c591461069c576103a3565b8063169e69bd1461057c57806318160ddd146105fa5780631882140014610614578063225ab94e1461061c576103a3565b8063081812fc11610382578063081812fc14610484578063095ea7b3146104a15780630dd4cf9a146104cf57806314d12e0a1461055c576103a3565b80623379d7146103a857806301ffc9a7146103cc57806306fdde0314610407575b600080fd5b6103b0611223565b604080516001600160a01b039092168252519081900360200190f35b6103f3600480360360208110156103e257600080fd5b50356001600160e01b031916611233565b604080519115158252519081900360200190f35b61040f611252565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610449578181015183820152602001610431565b50505050905090810190601f1680156104765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103b06004803603602081101561049a57600080fd5b50356112e8565b6104cd600480360360408110156104b757600080fd5b506001600160a01b03813516906020013561134a565b005b6104ec600480360360208110156104e557600080fd5b5035611472565b6040518088815260200187815260200186815260200185600481111561050e57fe5b60ff16815260200184600581111561052257fe5b60ff16815260200183600281111561053657fe5b60ff1681526020018260ff1660ff16815260200197505050505050505060405180910390f35b61040f6004803603602081101561057257600080fd5b503560ff16611703565b6104cd6004803603604081101561059257600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105bc57600080fd5b8201836020820111156105ce57600080fd5b803590602001918460208302840111600160201b831117156105ef57600080fd5b509092509050611918565b610602611aeb565b60408051918252519081900360200190f35b61040f611af1565b6104cd60048036036101a081101561063357600080fd5b50803590602001611b14565b6104cd6004803603606081101561065557600080fd5b506001600160a01b03813581169160208101359091169060400135611e4b565b61067d611ea7565b6040805161ffff9092168252519081900360200190f35b61040f611ead565b610602600480360360408110156106b257600080fd5b506001600160a01b038135169060200135611ed0565b61040f600480360360208110156106de57600080fd5b5035611f4f565b6104cd600480360360208110156106fb57600080fd5b50356001600160a01b03166120cf565b6104cd612194565b6106026004803603606081101561072957600080fd5b5060ff8135811691602081013582169160409091013516612207565b6106026004803603606081101561075b57600080fd5b5060ff813581169160208101359091169060400135612268565b6104cd6004803603606081101561078b57600080fd5b506001600160a01b0381358116916020810135909116906040013561228b565b6107c8600480360360208110156107c157600080fd5b50356122a6565b604051828152602081018261018080838360005b838110156107f45781810151838201526020016107dc565b505050509050019250505060405180910390f35b6104cd6004803603602081101561081e57600080fd5b50356001600160a01b0316612507565b6106026004803603602081101561084457600080fd5b503561260d565b6104cd6004803603604081101561086157600080fd5b81359190810190604081016020820135600160201b81111561088257600080fd5b82018360208201111561089457600080fd5b803590602001918460018302840111600160201b831117156108b557600080fd5b509092509050612673565b6103f3612881565b6103b0600480360360208110156108de57600080fd5b503561288a565b6103b06128e4565b6104cd6004803603602081101561090357600080fd5b50356001600160a01b03166128f9565b6106026004803603602081101561092957600080fd5b50356001600160a01b0316612941565b6109596004803603602081101561094f57600080fd5b503560ff166129a9565b6040518084600481111561096957fe5b60ff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156109ae578181015183820152602001610996565b50505050905090810190601f1680156109db5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610a0e5781810151838201526020016109f6565b50505050905090810190601f168015610a3b5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b61067d60048036036040811015610a6257600080fd5b5060ff81358116916020013516612ae9565b6104cd612b0a565b610ac3600480360360a0811015610a9257600080fd5b506001600160a01b038135169060208101359060ff6040820135811691606081013582169160809091013516612b6c565b6040805192835260208301919091528051918290030190f35b61060260048036036040811015610af257600080fd5b5060ff8135169060200135612e33565b6103f3612e50565b61040f612e55565b6104cd60048036036020811015610b2857600080fd5b50356001600160a01b0316612eb6565b6104cd60048036036020811015610b4e57600080fd5b50356001600160a01b0316612ef2565b6104cd60048036036040811015610b7457600080fd5b506001600160a01b0381351690602001351515612f2e565b61067d613033565b610bba60048036036040811015610baa57600080fd5b5060ff8135169060200135613039565b60405180878152602001868152602001858152602001846004811115610bdc57fe5b60ff168152602001836002811115610bf057fe5b60ff1681526020018260ff1660ff168152602001965050505050505060405180910390f35b6104ec60048036036040811015610c2b57600080fd5b5060ff813516906020013561317e565b610c5860048036036020811015610c5157600080fd5b5035613362565b60405180826001811115610c6857fe5b60ff16815260200191505060405180910390f35b6104cd60048036036080811015610c9257600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610ccc57600080fd5b820183602082011115610cde57600080fd5b803590602001918460018302840111600160201b83111715610cff57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506133a2945050505050565b61067d60048036036020811015610d5657600080fd5b503560ff16613400565b6103f3613416565b61060260048036036060811015610d7e57600080fd5b5060ff8135811691602081013582169160409091013516613424565b61067d613447565b61040f60048036036020811015610db857600080fd5b503561344c565b610ac3600480360360c0811015610dd557600080fd5b506001600160a01b038135169060208101359060ff60408201358116916060810135821691608082013581169160a001351661359b565b610bba60048036036020811015610e2257600080fd5b503561397f565b6103f360048036036040811015610e3f57600080fd5b506001600160a01b0381358116916020013516613a9b565b61040f60048036036020811015610e6d57600080fd5b5035613ac9565b6104cd60048036036020811015610e8a57600080fd5b50356001600160a01b0316613b89565b6104cd60048036036060811015610eb057600080fd5b60ff8235169190810190604081016020820135600160201b811115610ed457600080fd5b820183602082011115610ee657600080fd5b803590602001918460018302840111600160201b83111715610f0757600080fd5b919390929091602081019035600160201b811115610f2457600080fd5b820183602082011115610f3657600080fd5b803590602001918460018302840111600160201b83111715610f5757600080fd5b509092509050613c43565b6106026004803603610100811015610f7957600080fd5b60ff8235169190810190604081016020820135600160201b811115610f9d57600080fd5b820183602082011115610faf57600080fd5b803590602001918460208302840111600160201b83111715610fd057600080fd5b9193909260ff833581169360208101358216936040820135831693606083013590931692909160a081019060800135600160201b81111561101057600080fd5b82018360208201111561102257600080fd5b803590602001918460018302840111600160201b8311171561104357600080fd5b919390929091602081019035600160201b81111561106057600080fd5b82018360208201111561107257600080fd5b803590602001918460018302840111600160201b8311171561109357600080fd5b509092509050613e82565b6110bb600480360360208110156110b457600080fd5b5035614299565b604051808981526020018860048111156110d157fe5b60ff168152602001806020018760028111156110e957fe5b60ff16815260200186600b8111156110fd57fe5b60ff16815260200185600481111561111157fe5b60ff1681526020018460ff1660ff16815260200180602001838103835289818151815260200191508051906020019060200280838360005b83811015611161578181015183820152602001611149565b50505050905001838103825284818151815260200191508051906020019080838360005b8381101561119d578181015183820152602001611185565b50505050905090810190601f1680156111ca5780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390f35b6103f3600480360360408110156111f657600080fd5b5060ff81351690602001356145aa565b61040f6004803603602081101561121c57600080fd5b50356145ca565b601c546001600160a01b03165b90565b6001600160e01b03191660009081526004602052604090205460ff1690565b600d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112de5780601f106112b3576101008083540402835291602001916112de565b820191906000526020600020905b8154815290600101906020018083116112c157829003601f168201915b5050505050905090565b60006112f3826148a8565b61132e5760405162461bcd60e51b815260040180806020018281038252602c815260200180615eaf602c913960400191505060405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006113558261288a565b9050806001600160a01b0316836001600160a01b031614156113a85760405162461bcd60e51b8152600401808060200182810382526021815260200180615f266021913960400191505060405180910390fd5b806001600160a01b03166113ba6148c5565b6001600160a01b031614806113db57506113db816113d66148c5565b613a9b565b6114165760405162461bcd60e51b8152600401808060200182810382526038815260200180615e036038913960400191505060405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000806000806000806000601080549050881061148e57600080fd5b6114966159a7565b601089815481106114a357fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff1660048111156114f857fe5b600481111561150357fe5b81526020016003820160019054906101000a900460ff16600181111561152557fe5b600181111561153057fe5b905250905060008160800151600181111561154757fe5b1461155157600080fd5b6115596159e0565b601260008360600151600481111561156d57fe5b60ff1660ff16815260200190815260200160002082602001518154811061159057fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015611624576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116115f35790505b505050918352505060048281015460209092019160ff169081111561164557fe5b600481111561165057fe5b81526020016004820160019054906101000a900460ff16600581111561167257fe5b600581111561167d57fe5b81526020016004820160029054906101000a900460ff16600281111561169f57fe5b60028111156116aa57fe5b81526004919091015460ff6301000000909104166020918201528151908201516040830151608084015160a085015160c086015160e090960151949e50929c50909a509850965090945092505050919395979092949650565b606061170d615a2c565b6014600084600481111561171d57fe5b60ff908116825260208201929092526040908101600020815160608101909252805491929091839116600481111561175157fe5b600481111561175c57fe5b8152602001600182018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117f95780601f106117ce576101008083540402835291602001916117f9565b820191906000526020600020905b8154815290600101906020018083116117dc57829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801561188b5780601f106118605761010080835404028352916020019161188b565b820191906000526020600020905b81548152906001019060200180831161186e57829003601f168201915b50505050508152505090506000816020015151116118a857600080fd5b6118b68282602001516148c9565b91506118dc8260405180604001604052806002815260200161040560f31b8152506148c9565b91506118ec8282604001516148c9565b915061191182604051806040016040528060018152602001602960f81b8152506148c9565b9392505050565b801580159061192957506101008111155b61193257600080fd5b600080805b60ff8116841115611a245784848260ff1681811061195157fe5b905060200201359250601080549050831061196b57600080fd5b6119748361288a565b6001600160a01b0316336001600160a01b0316146119cf576040805162461bcd60e51b815260206004820152601360248201527226bab9ba103132903a37b5b2b71037bbb732b960691b604482015290519081900360640190fd5b6000838152601560205260409020546001600160a01b03878116911614611a1c57600083815260156020526040902080546001600160a01b0319166001600160a01b038816179055600191505b600101611937565b5080611a77576040805162461bcd60e51b815260206004820152601d60248201527f4e6f20756e68616e646c6564207072696d657320737065636966696564000000604482015290519081900360640190fd5b846001600160a01b03167f571f01a38e9f9580bf7e012e93cbf1db0f5741a6260c70ca67325de02fec78f3858560405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a25050505050565b600b5490565b6040518060400160405280600781526020016620bb30b9ba30b960c91b81525081565b6010548210611b2257600080fd5b611b2b8261288a565b6001600160a01b0316336001600160a01b03161480611b6057506000828152601560205260409020546001600160a01b031633145b611b9b5760405162461bcd60e51b8152600401808060200182810382526027815260200180615fa46027913960400191505060405180910390fd5b611ba36159a7565b60108381548110611bb057fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115611c0557fe5b6004811115611c1057fe5b81526020016003820160019054906101000a900460ff166001811115611c3257fe5b6001811115611c3d57fe5b9052509050600081608001516001811115611c5457fe5b14611c5e57600080fd5b60006012600083606001516004811115611c7457fe5b60ff1660ff168152602001908152602001600020826020015181548110611c9757fe5b6000918252602082206005909102019150805b600c8160ff161015611d58578060ff16600c1115611d4b57826003018160ff16600c8110611cd457fe5b602081049091015460ff601f9092166101000a900416158015611d095750848160ff16600c8110611d0157fe5b602002013515155b15611d46576001836003018260ff16600c8110611d2257fe5b602091828204019190066101000a81548160ff021916908315150217905550600191505b611d50565b611d58565b600101611caa565b5080611dab576040805162461bcd60e51b815260206004820152601c60248201527f4e6f207265757361626c65207472616974732073706563696669656400000000604482015290519081900360640190fd5b600085815260156020908152604080832080546001600160a01b03191690555187815233927fbbb2a94727e40c0fd33d28dc12b7474244c1d2add15fe036b15a550b79905192928992600388019290916101a0830191849184015b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411611e0657905050509250505060405180910390a25050505050565b611e5c611e566148c5565b82614984565b611e975760405162461bcd60e51b8152600401808060200182810382526031815260200180615f476031913960400191505060405180910390fd5b611ea2838383614a20565b505050565b61138881565b6040518060400160405280600781526020016620ab20a9aa20a960c91b81525081565b6000611edb83612941565b8210611f185760405162461bcd60e51b815260040180806020018281038252602b815260200180615cbe602b913960400191505060405180910390fd5b6001600160a01b0383166000908152600960205260409020805483908110611f3c57fe5b9060005260206000200154905092915050565b6010546060908210611f6057600080fd5b611f686159a7565b60108381548110611f7557fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115611fca57fe5b6004811115611fd557fe5b81526020016003820160019054906101000a900460ff166001811115611ff757fe5b600181111561200257fe5b90525090506000808260800151600181111561201a57fe5b1461206d57601360008360600151600481111561203357fe5b60ff1660ff16815260200190815260200160002082602001518154811061205657fe5b9060005260206000209060040201600201546120b7565b601260008360600151600481111561208157fe5b60ff1660ff1681526020019081526020016000208260200151815481106120a457fe5b9060005260206000209060050201600201545b90506120c7826060015182614a3f565b949350505050565b6120e060023363ffffffff614dff16565b6120e957600080fd5b336001600160a01b03821614156120ff57600080fd5b6000612111818363ffffffff614dff16565b1561212b5761212760008363ffffffff614e6616565b5060015b61213c60018363ffffffff614dff16565b156121565761215260018363ffffffff614e6616565b5060015b61216760028363ffffffff614dff16565b156121815761217d60028363ffffffff614e6616565b5060015b60018115151461219057600080fd5b5050565b6121a560003363ffffffff614dff16565b6121ae57600080fd5b60035460ff166121bd57600080fd5b600354610100900460ff16156121d257600080fd5b6003805460ff191690556040517f0e5e3b3fb504c22cf5c42fa07d521225937514c654007e1f12646f89768d6f9490600090a1565b6000601b600085600481111561221957fe5b60ff1660ff168152602001908152602001600020600084600b81111561223b57fe5b60ff9081168252602080830193909352604091820160009081209186168152925290205490509392505050565b601a60209081526000938452604080852082529284528284209052825290205481565b611ea2838383604051806020016040528060008152506133a2565b60006122b0615a4e565b60105483106122be57600080fd5b6122c66159a7565b601084815481106122d357fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff16600481111561232857fe5b600481111561233357fe5b81526020016003820160019054906101000a900460ff16600181111561235557fe5b600181111561236057fe5b905250905060008160800151600181111561237757fe5b1461238157600080fd5b6123896159e0565b601260008360600151600481111561239d57fe5b60ff1660ff1681526020019081526020016000208260200151815481106123c057fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015612454576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116124235790505b505050918352505060048281015460209092019160ff169081111561247557fe5b600481111561248057fe5b81526020016004820160019054906101000a900460ff1660058111156124a257fe5b60058111156124ad57fe5b81526020016004820160029054906101000a900460ff1660028111156124cf57fe5b60028111156124da57fe5b8152600491909101546301000000900460ff16602090910152805160609091015190969095509350505050565b61251860003363ffffffff614dff16565b61252157600080fd5b60035460ff1661253057600080fd5b600354610100900460ff161561254557600080fd5b6000819050806001600160a01b031663e486b6816040518163ffffffff1660e01b815260040160206040518083038186803b15801561258357600080fd5b505afa158015612597573d6000803e3d6000fd5b505050506040513d60208110156125ad57600080fd5b50516125b857600080fd5b601c80546001600160a01b0384166001600160a01b0319909116811790915560408051918252517f13151dbeeb461e21144c44310d3f712709198f403d9e3833f08601071704deb19181900360200190a15050565b6000612617611aeb565b82106126545760405162461bcd60e51b815260040180806020018281038252602c815260200180615f78602c913960400191505060405180910390fd5b600b828154811061266157fe5b90600052602060002001549050919050565b61268460003363ffffffff614dff16565b61268d57600080fd5b60035460ff161561269d57600080fd5b601183815481106126aa57fe5b6000918252602082206001600590920201015460ff16906012908260048111156126d057fe5b60ff1681526020810191909152604001600020541580156127125750601360008260048111156126fc57fe5b60ff168152602081019190915260400160002054155b61271b57600080fd5b601154841061272957600080fd5b60606128126011868154811061273b57fe5b6000918252602091829020600460059092020101805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156127d15780601f106127a6576101008083540402835291602001916127d1565b820191906000526020600020905b8154815290600101906020018083116127b457829003601f168201915b505050505085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506148c992505050565b9050806011868154811061282257fe5b90600052602060002090600502016004019080519060200190612846929190615a6d565b506040805186815290517f1ac2a8040df3df1374b56e8c1a1d073cc9bba1d7d18e7d59dd86be04351e97cc9181900360200190a15050505050565b60035460ff1681565b6000818152600560205260408120546001600160a01b0316806128de5760405162461bcd60e51b8152600401808060200182810382526029815260200180615e656029913960400191505060405180910390fd5b92915050565b6003546201000090046001600160a01b031681565b61290a60003363ffffffff614dff16565b61291357600080fd5b61292460028263ffffffff614ecd16565b61293560028263ffffffff614dff16565b61293e57600080fd5b50565b60006001600160a01b0382166129885760405162461bcd60e51b815260040180806020018281038252602a815260200180615e3b602a913960400191505060405180910390fd5b6001600160a01b03821660009081526007602052604090206128de90614f4e565b6014602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff909216949293909290830182828015612a4d5780601f10612a2257610100808354040283529160200191612a4d565b820191906000526020600020905b815481529060010190602001808311612a3057829003601f168201915b50505060028085018054604080516020601f6000196101006001871615020190941695909504928301859004850281018501909152818152959695945090925090830182828015612adf5780601f10612ab457610100808354040283529160200191612adf565b820191906000526020600020905b815481529060010190602001808311612ac257829003601f168201915b5050505050905083565b601860209081526000928352604080842090915290825290205461ffff1681565b612b1b60003363ffffffff614dff16565b612b2457600080fd5b60035460ff1615612b3457600080fd5b6003805460ff191660011790556040517fab35696f06e428ebc5ceba8cd17f8fed287baf43440206d1943af1ee53e6d26790600090a1565b600080612b8060013363ffffffff614dff16565b612b8957600080fd5b60035460ff1615612b9957600080fd5b85612ba357600080fd5b60166000866004811115612bb357fe5b60ff9081168252602080830193909352604091820160009081208a82529093529120541615612be157600080fd5b60008360ff16118015612bf8575060648360ff1611155b612c0157600080fd5b61627060196000876004811115612c1457fe5b60ff16815260208101919091526040016000205461ffff1610612c3657600080fd5b60136000866004811115612c4657fe5b60ff1681526020810191909152604001600020549050612c6a878288886001614f52565b915060136000866004811115612c7c57fe5b60ff1660ff1681526020019081526020016000206040518060c00160405280848152602001838152602001888152602001876004811115612cb957fe5b8152602001866002811115612cca57fe5b815260ff8616602091820152825460018181018086556000958652948390208451600493840290910190815592840151838201556040840151600284015560608401516003840180549193909260ff1990921691908490811115612d2a57fe5b0217905550608082015160038201805461ff001916610100836002811115612d4e57fe5b021790555060a08201518160030160026101000a81548160ff021916908360ff16021790555050505060196000866004811115612d8757fe5b60ff1681526020808201929092526040908101600020805461ffff8082166001011661ffff1990911617905580518481529182018390527fd6e5b8cb521b8e2deca8334964545247f158fa2e98a568e1e11671dd4697bf209184918491899189918c918101846004811115612df857fe5b60ff168152602001836002811115612e0c57fe5b60ff1681526020018281526020019550505050505060405180910390a19550959350505050565b601760209081526000928352604080842090915290825290205481565b600190565b600e8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112de5780601f106112b3576101008083540402835291602001916112de565b612ec760003363ffffffff614dff16565b612ed057600080fd5b612ee160018263ffffffff614ecd16565b61293560018263ffffffff614dff16565b612f0360003363ffffffff614dff16565b612f0c57600080fd5b612f1d60008263ffffffff614ecd16565b61293560008263ffffffff614dff16565b612f366148c5565b6001600160a01b0316826001600160a01b03161415612f9c576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060086000612fa96148c5565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155612fed6148c5565b60408051841515815290516001600160a01b0392909216917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319181900360200190a35050565b61627081565b6000806000806000806013600089600481111561305257fe5b60ff168152602081019190915260400160002054871061307157600080fd5b613079615aeb565b601360008a600481111561308957fe5b60ff1660ff16815260200190815260200160002088815481106130a857fe5b90600052602060002090600402016040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff1660048111156130fd57fe5b600481111561310857fe5b81526020016003820160019054906101000a900460ff16600281111561312a57fe5b600281111561313557fe5b81526003919091015462010000900460ff1660209182015281519082015160408301516060840151608085015160a090950151939e929d50909b50995091975095509350505050565b6000806000806000806000601260008a600481111561319957fe5b60ff16815260208101919091526040016000205488106131b857600080fd5b6131c06159e0565b601260008b60048111156131d057fe5b60ff1660ff16815260200190815260200160002089815481106131ef57fe5b90600052602060002090600502016040518061010001604052908160008201548152602001600182015481526020016002820154815260200160038201600c806020026040519081016040528092919082600c8015613283576020028201916000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116132525790505b505050918352505060048281015460209092019160ff16908111156132a457fe5b60048111156132af57fe5b81526020016004820160019054906101000a900460ff1660058111156132d157fe5b60058111156132dc57fe5b81526020016004820160029054906101000a900460ff1660028111156132fe57fe5b600281111561330957fe5b81526004919091015460ff6301000000909104166020918201528151908201516040830151608084015160a085015160c086015160e090960151949d50929b509099509750955090935091505092959891949750929550565b601054600090821061337357600080fd5b6010828154811061338057fe5b6000918252602090912060049091020160030154610100900460ff1692915050565b6133b36133ad6148c5565b83614984565b6133ee5760405162461bcd60e51b8152600401808060200182810382526031815260200180615f476031913960400191505060405180910390fd5b6133fa8484848461528a565b50505050565b60196020526000908152604090205461ffff1681565b600354610100900460ff1681565b601b60209081526000938452604080852082529284528284209052825290205481565b60c881565b601054606090821061345d57600080fd5b601c546040805163c87b56dd60e01b81526004810185905290516001600160a01b039092169163c87b56dd91602480820192600092909190829003018186803b1580156134a957600080fd5b505afa1580156134bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156134e657600080fd5b8101908080516040519392919084600160201b82111561350557600080fd5b90830190602082018581111561351a57600080fd5b8251600160201b81118282018810171561353357600080fd5b82525081516020918201929091019080838360005b83811015613560578181015183820152602001613548565b50505050905090810190601f16801561358d5780820380516001836020036101000a031916815260200191505b506040525050509050919050565b6000806135af60013363ffffffff614dff16565b6135b857600080fd5b60035460ff16156135c857600080fd5b6001600160a01b0388166135db57600080fd5b866135e557600080fd5b601660008760048111156135f557fe5b60ff9081168252602080830193909352604091820160009081208b8252909352912054161561362357600080fd5b60008360ff1611801561363a575060648360ff1611155b61364357600080fd5b60006018600088600481111561365557fe5b60ff1660ff168152602001908152602001600020600087600581111561367757fe5b60ff168152602081019190915260400160009081205461ffff16915086600581111561369f57fe5b146136bb5761138861ffff8216106136b657600080fd5b6136cc565b60c861ffff8216106136cc57600080fd5b601260008860048111156136dc57fe5b60ff1660ff16815260200190815260200160002080549050915061370489838a8a6000614f52565b925061370e615a4e565b6012600089600481111561371e57fe5b60ff1660ff1681526020019081526020016000206040518061010001604052808681526020018581526020018b81526020018381526020018a600481111561376257fe5b815260200189600581111561377357fe5b815260200188600281111561378457fe5b815260ff881660209182015282546001818101808655600095865294839020845160059093020191825591830151918101919091556040820151600282015560608201516137d8906003830190600c615b18565b5060808201518160040160006101000a81548160ff021916908360048111156137fd57fe5b021790555060a082015160048201805461ff00191661010083600581111561382157fe5b021790555060c082015160048201805462ff000019166201000083600281111561384757fe5b021790555060e08201518160040160036101000a81548160ff021916908360ff1602179055505050506018600089600481111561388057fe5b60ff1660ff16815260200190815260200160002060008860058111156138a257fe5b60ff1660ff168152602001908152602001600020600081819054906101000a900461ffff168092919060010191906101000a81548161ffff021916908361ffff160217905550507fcda0c43783a712d26fef88c79742e07db82ff51962220e36f70cb852dcd0c4ef84848a8a8a8e6040518087815260200186815260200185600481111561392c57fe5b60ff16815260200184600581111561394057fe5b60ff16815260200183600281111561395457fe5b60ff168152602001828152602001965050505050505060405180910390a15050965096945050505050565b600080600080600080601080549050871061399957600080fd5b6139a16159a7565b601088815481106139ae57fe5b90600052602060002090600402016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff166004811115613a0357fe5b6004811115613a0e57fe5b81526020016003820160019054906101000a900460ff166001811115613a3057fe5b6001811115613a3b57fe5b9052509050600181608001516001811115613a5257fe5b14613a5c57600080fd5b613a64615aeb565b6013600083606001516004811115613a7857fe5b60ff1660ff1681526020019081526020016000208260200151815481106130a857fe5b6001600160a01b03918216600090815260086020908152604080832093909416825291909152205460ff1690565b6011546060908210613ada57600080fd5b60118281548110613ae757fe5b6000918252602091829020600360059092020101805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015613b7d5780601f10613b5257610100808354040283529160200191613b7d565b820191906000526020600020905b815481529060010190602001808311613b6057829003601f168201915b50505050509050919050565b613b9a60003363ffffffff614dff16565b613ba357600080fd5b60035460ff16613bb257600080fd5b600354610100900460ff1615613bc757600080fd5b6001600160a01b038116613bda57600080fd5b6003805461010061ff00199091161762010000600160b01b031916620100006001600160a01b0384169081029190911790915560408051918252517f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa446199305916020908290030190a150565b613c5460003363ffffffff614dff16565b613c5d57600080fd5b8460126000826004811115613c6e57fe5b60ff168152602081019190915260400160002054158015613cb0575060136000826004811115613c9a57fe5b60ff168152602081019190915260400160002054155b613cb957600080fd5b8315801590613cc757508115155b613cd057600080fd5b6040518060600160405280876004811115613ce757fe5b815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f87018190048102820181019092528581529181019190869086908190840183828082843760009201829052509390945250601492508990506004811115613d7057fe5b60ff168152602081019190915260400160002081518154829060ff19166001836004811115613d9b57fe5b02179055506020828101518051613db89260018501920190615a6d565b5060408201518051613dd4916002840191602090910190615a6d565b509050507fae7bd40c57594fc1eada1cdb57956d2e028bf0e14959f3ff73b31e884bde0563868686868660405180866004811115613e0e57fe5b60ff16815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a1505050505050565b6000613e94813363ffffffff614dff16565b613e9d57600080fd5b60035460ff1615613ead57600080fd5b8b60126000826004811115613ebe57fe5b60ff168152602081019190915260400160002054158015613f00575060136000826004811115613eea57fe5b60ff168152602081019190915260400160002054155b613f0957600080fd5b8a613f1357600080fd5b84613f1d57600080fd5b82613f2757600080fd5b601180549050915060116040518061012001604052808481526020018f6004811115613f4f57fe5b81526020018c6002811115613f6057fe5b81526020018b600b811115613f7157fe5b81526020018a6004811115613f8257fe5b81526020018960ff1681526020018e8e80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505090825250604080516020601f8b0181900481028201810190925289815291810191908a908a9081908401838280828437600092019190915250505090825250604080516020601f89018190048102820181019092528781529181019190889088908190840183828082843760009201829052509390945250508354600181810180875595835260209283902085516005909302019182559184015181830180549294509092909160ff19169083600481111561407a57fe5b0217905550604082015160018201805461ff00191661010083600281111561409e57fe5b0217905550606082015160018201805462ff000019166201000083600b8111156140c457fe5b0217905550608082015160018201805463ff000000191663010000008360048111156140ec57fe5b021790555060a082015160018201805460ff909216600160201b0264ff000000001990921691909117905560c08201518051614132916002840191602090910190615ba6565b5060e0820151805161414e916003840191602090910190615a6d565b50610100820151805161416b916004840191602090910190615a6d565b5050505081601b60008f600481111561418057fe5b60ff1660ff16815260200190815260200160002060008b600b8111156141a257fe5b60ff1660ff16815260200190815260200160002060008960ff1660ff168152602001908152602001600020819055507fafe2beb8771ed6e9287abf691a85f85c4df73ce22e7c53d4b01d755fddba0352828e8b8b8b8b8b6040518088815260200187600481111561420f57fe5b60ff16815260200186600b81111561422357fe5b60ff16815260200185600481111561423757fe5b60ff1681526020018460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039a509098505050505050505050a1509b9a5050505050505050505050565b6000806060600080600080606060118054905089106142b757600080fd5b6142bf615c15565b60118a815481106142cc57fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff16600481111561430e57fe5b600481111561431957fe5b81526020016001820160019054906101000a900460ff16600281111561433b57fe5b600281111561434657fe5b81526020016001820160029054906101000a900460ff16600b81111561436857fe5b600b81111561437357fe5b81526020016001820160039054906101000a900460ff16600481111561439557fe5b60048111156143a057fe5b81526001820154600160201b900460ff16602080830191909152600283018054604080518285028101850182528281529401939283018282801561442d57602002820191906000526020600020906000905b82829054906101000a900460ff16600581111561440b57fe5b8152602060019283018181049485019490930390920291018084116143f25790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156144c15780601f10614496576101008083540402835291602001916144c1565b820191906000526020600020905b8154815290600101906020018083116144a457829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156145555780601f1061452a57610100808354040283529160200191614555565b820191906000526020600020905b81548152906001019060200180831161453857829003601f168201915b5050505050815250509050806000015181602001518260c001518360400151846060015185608001518660a001518760e001518595508090509850985098509850985098509850985050919395975091939597565b601660209081526000928352604080842090915290825290205460ff1681565b60606145dd60003363ffffffff614dff16565b6145e657600080fd5b60115482106145f457600080fd5b6145fc615c15565b6011838154811061460957fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff16600481111561464b57fe5b600481111561465657fe5b81526020016001820160019054906101000a900460ff16600281111561467857fe5b600281111561468357fe5b81526020016001820160029054906101000a900460ff16600b8111156146a557fe5b600b8111156146b057fe5b81526020016001820160039054906101000a900460ff1660048111156146d257fe5b60048111156146dd57fe5b81526001820154600160201b900460ff16602080830191909152600283018054604080518285028101850182528281529401939283018282801561476a57602002820191906000526020600020906000905b82829054906101000a900460ff16600581111561474857fe5b81526020600192830181810494850194909303909202910180841161472f5790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156147fe5780601f106147d3576101008083540402835291602001916147fe565b820191906000526020600020905b8154815290600101906020018083116147e157829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529382019392918301828280156148925780601f1061486757610100808354040283529160200191614892565b820191906000526020600020905b81548152906001019060200180831161487557829003601f168201915b5050509190925250505061010001519392505050565b6000908152600560205260409020546001600160a01b0316151590565b3390565b606082826040516020018083805190602001908083835b602083106148ff5780518252601f1990920191602091820191016148e0565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106149475780518252601f199092019160209182019101614928565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052905092915050565b600061498f826148a8565b6149ca5760405162461bcd60e51b815260040180806020018281038252602c815260200180615dd7602c913960400191505060405180910390fd5b60006149d58361288a565b9050806001600160a01b0316846001600160a01b03161480614a105750836001600160a01b0316614a05846112e8565b6001600160a01b0316145b806120c757506120c78185613a9b565b614a2b8383836152dc565b614a358382615420565b611ea28282615515565b606060008211614a4e57600080fd5b60606040518060c0016040528060988152602001615d1b60989139905061010060ff600080808080614a7e615c15565b60005b600b60ff821611614dc65760ff8116890a88810297508c8816965094508515614dbe5760008160ff1611614ab55785614ac0565b848681614abe57fe5b045b93508315614dbe57601b60008e6004811115614ad857fe5b60ff9081168252602080830193909352604091820160009081208583168252845282812091881681529252902054601180549194509084908110614b1857fe5b906000526020600020906005020160405180610120016040529081600082015481526020016001820160009054906101000a900460ff166004811115614b5a57fe5b6004811115614b6557fe5b81526020016001820160019054906101000a900460ff166002811115614b8757fe5b6002811115614b9257fe5b81526020016001820160029054906101000a900460ff16600b811115614bb457fe5b600b811115614bbf57fe5b81526020016001820160039054906101000a900460ff166004811115614be157fe5b6004811115614bec57fe5b81526001820154600160201b900460ff166020808301919091526002830180546040805182850281018501825282815294019392830182828015614c7957602002820191906000526020600020906000905b82829054906101000a900460ff166005811115614c5757fe5b815260206001928301818104948501949093039092029101808411614c3e5790505b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152938201939291830182828015614d0d5780601f10614ce257610100808354040283529160200191614d0d565b820191906000526020600020905b815481529060010190602001808311614cf057829003601f168201915b505050918352505060048201805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152938201939291830182828015614da15780601f10614d7657610100808354040283529160200191614da1565b820191906000526020600020905b815481529060010190602001808311614d8457829003601f168201915b5050505050815250509150614dbb8a8361010001516148c9565b99505b600101614a81565b50614def89604051806040016040528060068152602001651e17b9bb339f60d11b8152506148c9565b9c9b505050505050505050505050565b60006001600160a01b038216614e465760405162461bcd60e51b8152600401808060200182810382526022815260200180615edb6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b614e708282614dff565b614eab5760405162461bcd60e51b8152600401808060200182810382526021815260200180615e8e6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b614ed78282614dff565b15614f29576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b5490565b60035460009060ff1615614f6557600080fd5b601a6000846004811115614f7557fe5b60ff1660ff1681526020019081526020016000206000836001811115614f9757fe5b60ff1681526020808201929092526040908101600090812088825290925290205415614fc257600080fd5b6000826001811115614fd057fe5b141561500a5760126000846004811115614fe657fe5b60ff168152602081019190915260400160002054851461500557600080fd5b615039565b6013600084600481111561501a57fe5b60ff168152602081019190915260400160002054851461503957600080fd5b506010546150456159a7565b6040518060a0016040528083815260200187815260200186815260200185600481111561506e57fe5b815260200184600181111561507f57fe5b9052601080546001818101808455600093909352835160049283027f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672810191825560208601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67382015560408601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67482015560608601517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6759091018054969750949587959294919360ff1990911691849081111561515a57fe5b0217905550608082015160038201805461ff00191661010083600181111561517e57fe5b02179055505050506001601660008360600151600481111561519c57fe5b60ff168152602080820192909252604090810160009081208583015182529092528120805460ff19169215159290921790915581516060830151909160179160048111156151e657fe5b60ff1660ff168152602001908152602001600020600083604001518152602001908152602001600020819055508060000151601a60008360600151600481111561522c57fe5b60ff1660ff16815260200190815260200160002060008360800151600181111561525257fe5b60ff168152602080820192909252604090810160009081208584015182529092529020556152808783615553565b5095945050505050565b615295848484614a20565b6152a184848484615570565b6133fa5760405162461bcd60e51b8152600401808060200182810382526032815260200180615ce96032913960400191505060405180910390fd5b826001600160a01b03166152ef8261288a565b6001600160a01b0316146153345760405162461bcd60e51b8152600401808060200182810382526029815260200180615efd6029913960400191505060405180910390fd5b6001600160a01b0382166153795760405162461bcd60e51b8152600401808060200182810382526024815260200180615db36024913960400191505060405180910390fd5b615382816156c7565b6001600160a01b03831660009081526007602052604090206153a390615702565b6001600160a01b03821660009081526007602052604090206153c490615719565b60008181526005602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b03821660009081526009602052604081205461544a90600163ffffffff61572216565b6000838152600a60205260409020549091508082146154e5576001600160a01b038416600090815260096020526040812080548490811061548757fe5b906000526020600020015490508060096000876001600160a01b03166001600160a01b0316815260200190815260200160002083815481106154c557fe5b6000918252602080832090910192909255918252600a9052604090208190555b6001600160a01b038416600090815260096020526040902080549061550e906000198301615c65565b5050505050565b6001600160a01b0390911660009081526009602081815260408084208054868652600a84529185208290559282526001810183559183529091200155565b61555d8282615764565b6155678282615515565b61219081615895565b6000615584846001600160a01b03166158d9565b615590575060016120c7565b6000846001600160a01b031663150b7a026155a96148c5565b8887876040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561562e578181015183820152602001615616565b50505050905090810190601f16801561565b5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561567d57600080fd5b505af1158015615691573d6000803e3d6000fd5b505050506040513d60208110156156a757600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b6000818152600660205260409020546001600160a01b03161561293e57600090815260066020526040902080546001600160a01b0319169055565b805461571590600163ffffffff61572216565b9055565b80546001019055565b600061191183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615910565b6001600160a01b0382166157bf576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b6157c8816148a8565b1561581a576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b0319166001600160a01b03871690811790915583526007909152902061585990615719565b60405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906120c75750141592915050565b6000818484111561599f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561596457818101518382015260200161594c565b50505050905090810190601f1680156159915780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6040518060a00160405280600081526020016000815260200160008152602001600060048111156159d457fe5b81526020016000905290565b604051806101000160405280600081526020016000815260200160008152602001615a09615a4e565b81526020016000815260200160005b815260200160008152600060209091015290565b6040805160608101909152806000815260200160608152602001606081525090565b604051806101800160405280600c906020820280388339509192915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615aae57805160ff1916838001178555615adb565b82800160010185558215615adb579182015b82811115615adb578251825591602001919060010190615ac0565b50615ae7929150615c85565b5090565b6040518060c0016040528060008152602001600081526020016000815260200160006004811115615a1857fe5b600183019183908215615b9a5791602002820160005b83821115615b6b57835183826101000a81548160ff0219169083151502179055509260200192600101602081600001049283019260010302615b2e565b8015615b985782816101000a81549060ff0219169055600101602081600001049283019260010302615b6b565b505b50615ae7929150615c9f565b82805482825590600052602060002090601f01602090048101928215615b9a5791602002820160005b83821115615b6b57835183826101000a81548160ff02191690836005811115615bf457fe5b02179055509260200192600101602081600001049283019260010302615bcf565b604080516101208101909152600080825260208201908152602001600081526020016000815260200160008152602001600060ff1681526020016060815260200160608152602001606081525090565b815481835581811115611ea257600083815260209020611ea29181019083015b61123091905b80821115615ae75760008155600101615c8b565b61123091905b80821115615ae757805460ff19168155600101615ca556fe455243373231456e756d657261626c653a206f776e657220696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465723c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b222076657273696f6e3d22312e3122206865696768743d22313030307078222077696474683d22313030307078222076696577426f783d2230203020313030302031303030223e4552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c654552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e526f6c65733a206163636f756e7420697320746865207a65726f20616464726573734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564455243373231456e756d657261626c653a20676c6f62616c20696e646578206f7574206f6620626f756e64734d75737420626520746f6b656e206f776e6572206f7220617070726f7665642068616e646c6572a265627a7a7231582058dc70ca79f03c655381e9b8ffb65b62e19238f259a0093e34ed6dde4d524ae864736f6c634300050e0032

Deployed Bytecode Sourcemap

85436:6574:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85436:6574:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87784:145;;;:::i;:::-;;;;-1:-1:-1;;;;;87784:145:0;;;;;;;;;;;;;;26195:135;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26195:135:0;-1:-1:-1;;;;;;26195:135:0;;:::i;:::-;;;;;;;;;;;;;;;;;;53172:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;53172:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31157:204;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31157:204:0;;:::i;30439:425::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30439:425:0;;;;;;;;:::i;:::-;;75700:732;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;75700:732:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63518:506;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63518:506:0;;;;:::i;89008:816::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;89008:816:0;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;89008:816:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;89008:816:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;89008:816:0;;-1:-1:-1;89008:816:0;-1:-1:-1;89008:816:0;:::i;44813:96::-;;;:::i;:::-;;;;;;;;;;;;;;;;55945:45;;;:::i;90614:1391::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;90614:1391:0;;;;;;:::i;32840:292::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;32840:292:0;;;;;;;;;;;;;;;;;:::i;73217:51::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;55997:47;;;:::i;44422:232::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;44422:232:0;;;;;;;;:::i;72415:486::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72415:486:0;;:::i;14245:525::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14245:525:0;-1:-1:-1;;;;;14245:525:0;;:::i;15107:135::-;;;:::i;60926:298::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60926:298:0;;;;;;;;;;;;;;;;;;;;:::i;58541:103::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58541:103:0;;;;;;;;;;;;;;;;;;:::i;33794:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;33794:134:0;;;;;;;;;;;;;;;;;:::i;76696:490::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;76696:490:0;;:::i;:::-;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;76696:490:0;;;;;;;;;;;;;;;;;87057:549;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;87057:549:0;-1:-1:-1;;;;;87057:549:0;;:::i;45255:199::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45255:199:0;;:::i;66792:353::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;66792:353:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;66792:353:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;66792:353:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;66792:353:0;;-1:-1:-1;66792:353:0;-1:-1:-1;66792:353:0;:::i;10977:25::-;;;:::i;29780:228::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29780:228:0;;:::i;11044:33::-;;;:::i;13503:152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13503:152:0;-1:-1:-1;;;;;13503:152:0;;:::i;29343:211::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29343:211:0;-1:-1:-1;;;;;29343:211:0;;:::i;56841:60::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56841:60:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;56841:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56841:60:0;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;56841:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58019:75;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58019:75:0;;;;;;;;;;;:::i;14878:117::-;;;:::i;83180:1251::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;83180:1251:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;57752:79;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57752:79:0;;;;;;;;;:::i;86673:74::-;;;:::i;53372:89::-;;;:::i;13081:158::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13081:158:0;-1:-1:-1;;;;;13081:158:0;;:::i;13870:164::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13870:164:0;-1:-1:-1;;;;;13870:164:0;;:::i;31662:254::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;31662:254:0;;;;;;;;;;:::i;79651:60::-;;;:::i;80730:674::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;80730:674:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74496:681;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;74496:681:0;;;;;;;;;:::i;71972:195::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71972:195:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34665:272;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;34665:272:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;34665:272:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;34665:272:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;34665:272:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;34665:272:0;;-1:-1:-1;34665:272:0;;-1:-1:-1;;;;;34665:272:0:i;58250:58::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58250:58:0;;;;:::i;11009:28::-;;;:::i;58882:104::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58882:104:0;;;;;;;;;;;;;;;;;;;;:::i;73275:60::-;;;:::i;88231:222::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;88231:222:0;;:::i;77793:1541::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;77793:1541:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;81862:725::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81862:725:0;;:::i;32246:147::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;32246:147:0;;;;;;;;;;:::i;62575:188::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62575:188:0;;:::i;12622:261::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12622:261:0;-1:-1:-1;;;;;12622:261:0;;:::i;64330:438::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;64330:438:0;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;64330:438:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;64330:438:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;64330:438:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;64330:438:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;64330:438:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;64330:438:0;;-1:-1:-1;64330:438:0;-1:-1:-1;64330:438:0;:::i;65342:1112::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;65342:1112:0;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;65342:1112:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;65342:1112:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;65342:1112:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;65342:1112:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;65342:1112:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;65342:1112:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;65342:1112:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;65342:1112:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;65342:1112:0;;-1:-1:-1;65342:1112:0;-1:-1:-1;65342:1112:0;:::i;61770:637::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61770:637:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61770:637:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61770:637:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57368:72;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57368:72:0;;;;;;;;;:::i;63003:234::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63003:234:0;;:::i;87784:145::-;87898:23;;-1:-1:-1;;;;;87898:23:0;87784:145;;:::o;26195:135::-;-1:-1:-1;;;;;;26289:33:0;26265:4;26289:33;;;:20;:33;;;;;;;;;26195:135::o;53172:85::-;53244:5;53237:12;;;;;;;;-1:-1:-1;;53237:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53211:13;;53237:12;;53244:5;;53237:12;;53244:5;53237:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53172:85;:::o;31157:204::-;31216:7;31244:16;31252:7;31244;:16::i;:::-;31236:73;;;;-1:-1:-1;;;31236:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31329:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;31329:24:0;;31157:204::o;30439:425::-;30503:13;30519:16;30527:7;30519;:16::i;:::-;30503:32;;30560:5;-1:-1:-1;;;;;30554:11:0;:2;-1:-1:-1;;;;;30554:11:0;;;30546:57;;;;-1:-1:-1;;;30546:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30640:5;-1:-1:-1;;;;;30624:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;30624:21:0;;:62;;;;30649:37;30666:5;30673:12;:10;:12::i;:::-;30649:16;:37::i;:::-;30616:154;;;;-1:-1:-1;;;30616:154:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30783:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;30783:29:0;-1:-1:-1;;;;;30783:29:0;;;;;;;;;30828:28;;30783:24;;30828:28;;;;;;;30439:425;;;:::o;75700:732::-;75788:15;75814:14;75839;75864:21;75896:13;75920;75944;75995:8;:15;;;;75984:8;:26;75976:35;;;;;;76022:22;;:::i;:::-;76047:8;76056;76047:18;;;;;;;;;;;;;;;;;;76022:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76022:43:0;-1:-1:-1;76101:10:0;76084:7;:12;;;:27;;;;;;;;;76076:36;;;;;;76123:18;;:::i;:::-;76144;:45;76169:7;:18;;;76163:25;;;;;;;;76144:45;;;;;;;;;;;;;;;76190:7;:14;;;76144:61;;;;;;;;;;;;;;;;;;76123:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;76123:82:0;;;-1:-1:-1;;76123:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76238:8;;76261:12;;;;76288;;;;76315:16;;;;76346:12;;;;76373;;;;76400:13;;;;;76238:8;;-1:-1:-1;76261:12:0;;-1:-1:-1;76288:12:0;;-1:-1:-1;76315:16:0;-1:-1:-1;76346:12:0;-1:-1:-1;76373:12:0;;-1:-1:-1;76400:13:0;-1:-1:-1;;;75700:732:0;;;;;;;;;:::o;63518:506::-;63621:25;63664;;:::i;:::-;63692:23;:43;63722:11;63716:18;;;;;;;;63692:43;;;;;;;;;;;;;;;;;-1:-1:-1;63692:43:0;63664:71;;;;;;;;;;;;63692:43;;63664:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63664:71:0;;;-1:-1:-1;;63664:71:0;;;;;;;;;;;;;;;;-1:-1:-1;;63664:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63784:1;63760:6;:13;;;63754:27;:31;63746:40;;;;;;63811:37;63821:11;63834:6;:13;;;63811:9;:37::i;:::-;63797:51;;63873:28;63883:11;63873:28;;;;;;;;;;;;;-1:-1:-1;;;63873:28:0;;;:9;:28::i;:::-;63859:42;;63926:38;63936:11;63949:6;:14;;;63926:9;:38::i;:::-;63912:52;;63989:27;63999:11;63989:27;;;;;;;;;;;;;-1:-1:-1;;;63989:27:0;;;:9;:27::i;:::-;63975:41;63518:506;-1:-1:-1;;;63518:506:0:o;89008:816::-;89122:20;;;;;:47;;-1:-1:-1;89166:3:0;89146:23;;;89122:47;89114:56;;;;;;89181:15;;;89247:416;89265:20;;;;-1:-1:-1;89247:416:0;;;89317:9;;89327:1;89317:12;;;;;;;;;;;;;;;89307:22;;89362:8;:15;;;;89352:7;:25;89344:34;;;;;;89415:22;89429:7;89415:13;:22::i;:::-;-1:-1:-1;;;;;89401:36:0;:10;-1:-1:-1;;;;;89401:36:0;;89393:68;;;;;-1:-1:-1;;;89393:68:0;;;;;;;;;;;;-1:-1:-1;;;89393:68:0;;;;;;;;;;;;;;;89480:35;;;;:26;:35;;;;;;-1:-1:-1;;;;;89480:47:0;;;:35;;:47;89476:176;;89548:35;;;;:26;:35;;;;;:46;;-1:-1:-1;;;;;;89548:46:0;-1:-1:-1;;;;;89548:46:0;;;;;-1:-1:-1;;;89476:176:0;89287:3;;89247:416;;;;89681:16;89673:58;;;;;-1:-1:-1;;;89673:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;89796:8;-1:-1:-1;;;;;89776:40:0;;89806:9;;89776:40;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;89776:40:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;89776:40:0;;;;-1:-1:-1;89776:40:0;;-1:-1:-1;;;;89776:40:0;89008:816;;;;;:::o;44813:96::-;44884:10;:17;44813:96;:::o;55945:45::-;;;;;;;;;;;;;;-1:-1:-1;;;55945:45:0;;;;:::o;90614:1391::-;90774:8;:15;90763:26;;90755:35;;;;;;90892:23;90906:8;90892:13;:23::i;:::-;-1:-1:-1;;;;;90878:37:0;:10;-1:-1:-1;;;;;90878:37:0;;:91;;;-1:-1:-1;90933:36:0;;;;:26;:36;;;;;;-1:-1:-1;;;;;90933:36:0;90919:10;:50;90878:91;90870:153;;;;-1:-1:-1;;;90870:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91091:22;;:::i;:::-;91116:8;91125;91116:18;;;;;;;;;;;;;;;;;;91091:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91091:43:0;-1:-1:-1;91169:10:0;91153:7;:12;;;:26;;;;;;;;;91145:35;;;;;;91219:19;91241:18;:45;91266:7;:18;;;91260:25;;;;;;;;91241:45;;;;;;;;;;;;;;;91287:7;:14;;;91241:61;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91241:61:0;91370:323;91392:2;91388:1;:6;;;91370:323;;;91441:1;91420:22;;:18;:22;91416:266;;;91470:5;:16;;91487:1;91470:19;;;;;;;;;;;;;;;;;;;;;;;;;;91469:20;:38;;;;;91493:11;91505:1;91493:14;;;;;;;;;;;;;;;91469:38;91464:157;;;91555:4;91533:5;:16;;91550:1;91533:19;;;;;;;;;;;;;;;;;;:26;;;;;;;;;;;;;;;;;;91597:4;91582:19;;91464:157;91416:266;;;91661:5;;91416:266;91396:3;;91370:323;;;;91752:12;91744:53;;;;;-1:-1:-1;;;91744:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;91889:1;91842:36;;;:26;:36;;;;;;;;:49;;-1:-1:-1;;;;;;91842:49:0;;;91947:50;;;;91958:10;;91947:50;;91842:36;;91980:16;;;;91947:50;;;;;;91980:16;;91947:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90614:1391;;;;;:::o;32840:292::-;32984:41;33003:12;:10;:12::i;:::-;33017:7;32984:18;:41::i;:::-;32976:103;;;;-1:-1:-1;;;32976:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33092:32;33106:4;33112:2;33116:7;33092:13;:32::i;:::-;32840:292;;;:::o;73217:51::-;73264:4;73217:51;:::o;55997:47::-;;;;;;;;;;;;;;-1:-1:-1;;;55997:47:0;;;;:::o;44422:232::-;44502:7;44538:16;44548:5;44538:9;:16::i;:::-;44530:5;:24;44522:80;;;;-1:-1:-1;;;44522:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44620:19:0;;;;;;:12;:19;;;;;:26;;44640:5;;44620:26;;;;;;;;;;;;;;44613:33;;44422:232;;;;:::o;72415:486::-;72543:8;:15;72489:17;;72532:26;;72524:35;;;;;;72570:22;;:::i;:::-;72595:8;72604;72595:18;;;;;;;;;;;;;;;;;;72570:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72570:43:0;-1:-1:-1;72624:14:0;;72642:7;:12;;;:26;;;;;;;;;72641:192;;72761:22;:49;72790:7;:18;;;72784:25;;;;;;;;72761:49;;;;;;;;;;;;;;;72811:7;:14;;;72761:65;;;;;;;;;;;;;;;;;;:72;;;72641:192;;;72681:18;:45;72706:7;:18;;;72700:25;;;;;;;;72681:45;;;;;;;;;;;;;;;72727:7;:14;;;72681:61;;;;;;;;;;;;;;;;;;:68;;;72641:192;72624:209;;72850:43;72866:7;:18;;;72886:6;72850:15;:43::i;:::-;72844:49;72415:486;-1:-1:-1;;;;72415:486:0:o;14245:525::-;11358:22;:6;11369:10;11358:22;:10;:22;:::i;:::-;11350:31;;;;;;14321:10;-1:-1:-1;;;;;14321:22:0;;;;14313:31;;;;;;14355:13;14391:20;14355:13;14402:8;14391:20;:10;:20;:::i;:::-;14387:106;;;14428:23;:6;14442:8;14428:23;:13;:23;:::i;:::-;-1:-1:-1;14477:4:0;14387:106;14507:21;:7;14519:8;14507:21;:11;:21;:::i;:::-;14503:108;;;14545:24;:7;14560:8;14545:24;:14;:24;:::i;:::-;-1:-1:-1;14595:4:0;14503:108;14625:20;:6;14636:8;14625:20;:10;:20;:::i;:::-;14621:106;;;14662:23;:6;14676:8;14662:23;:13;:23;:::i;:::-;-1:-1:-1;14711:4:0;14621:106;14757:4;14745:16;;;;14737:25;;;;;;11392:1;14245:525;:::o;15107:135::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11922:6;;;;11914:15;;;;;;12112:8;;;;;;;12111:9;12103:18;;;;;;15186:6;:14;;-1:-1:-1;;15186:14:0;;;15216:18;;;;15195:5;;15216:18;15107:135::o;60926:298::-;61095:15;61135:35;:55;61177:11;61171:18;;;;;;;;61135:55;;;;;;;;;;;;;;;:69;61197:5;61191:12;;;;;;;;61135:69;;;;;;;;;;;;;;;;;;-1:-1:-1;61135:69:0;;;:81;;;;;;;;;;;-1:-1:-1;60926:298:0;;;;;:::o;58541:103::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;33794:134::-;33881:39;33898:4;33904:2;33908:7;33881:39;;;;;;;;;;;;:16;:39::i;76696:490::-;76795:15;76821:26;;:::i;:::-;76885:8;:15;76874:26;;76866:35;;;;;;76912:22;;:::i;:::-;76937:8;76946;76937:18;;;;;;;;;;;;;;;;;;76912:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76912:43:0;-1:-1:-1;76991:10:0;76974:7;:12;;;:27;;;;;;;;;76966:36;;;;;;77013:18;;:::i;:::-;77034;:45;77059:7;:18;;;77053:25;;;;;;;;77034:45;;;;;;;;;;;;;;;77080:7;:14;;;77034:61;;;;;;;;;;;;;;;;;;77013:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;77013:82:0;;;-1:-1:-1;;77013:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77128:8;;77151:16;;;;;77128:8;;77151:16;;-1:-1:-1;76696:490:0;-1:-1:-1;;;;76696:490:0:o;87057:549::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11922:6;;;;11914:15;;;;;;12112:8;;;;;;;12111:9;12103:18;;;;;;87255:34;87309:8;87255:63;;87395:17;-1:-1:-1;;;;;87395:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;87395:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87395:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;87395:37:0;87387:46;;;;;;87483:23;:34;;-1:-1:-1;;;;;87483:34:0;;-1:-1:-1;;;;;;87483:34:0;;;;;;;;87562:36;;;;;;;;;;;;;;;;12132:1;87057:549;:::o;45255:199::-;45313:7;45349:13;:11;:13::i;:::-;45341:5;:21;45333:78;;;;-1:-1:-1;;;45333:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45429:10;45440:5;45429:17;;;;;;;;;;;;;;;;45422:24;;45255:199;;;:::o;66792:353::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11741:6;;;;11740:7;11732:16;;;;;;66912:6;66919:8;66912:16;;;;;;;;;;;;;;;:27;:16;;;;;:27;;;;;60490:18;;66912:27;60509:18;;;;;;;;60490:38;;;;;;;;;;;;;-1:-1:-1;60490:38:0;:45;:50;:108;;;;;60544:22;:42;60573:11;60567:18;;;;;;;;60544:42;;;;;;;;;;;;;-1:-1:-1;60544:42:0;:49;:54;60490:108;60482:117;;;;;;66976:6;:13;66965:24;;66957:33;;;;;;67001:17;67021:37;67031:6;67038:8;67031:16;;;;;;;;;;;;;;;;;:20;:16;;;;;:20;67021:37;;;;;;;-1:-1:-1;;67021:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67031:20;67021:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67053:4;;67021:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;67021:9:0;;-1:-1:-1;;;67021:37:0:i;:::-;67001:57;;67092:3;67069:6;67076:8;67069:16;;;;;;;;;;;;;;;;;;:20;;:26;;;;;;;;;;;;:::i;:::-;-1:-1:-1;67111:26:0;;;;;;;;;;;;;;;;;60610:1;11759;66792:353;;;:::o;10977:25::-;;;;;;:::o;29780:228::-;29835:7;29871:20;;;:11;:20;;;;;;-1:-1:-1;;;;;29871:20:0;29910:19;29902:73;;;;-1:-1:-1;;;29902:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29995:5;29780:228;-1:-1:-1;;29780:228:0:o;11044:33::-;;;;;;-1:-1:-1;;;;;11044:33:0;;:::o;13503:152::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;13577:25;:6;13588:13;13577:25;:10;:25;:::i;:::-;13621;:6;13632:13;13621:25;:10;:25;:::i;:::-;13613:34;;;;;;13503:152;:::o;29343:211::-;29398:7;-1:-1:-1;;;;;29426:19:0;;29418:74;;;;-1:-1:-1;;;29418:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;29512:24:0;;;;;;:17;:24;;;;;:34;;:32;:34::i;56841:60::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;56841:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;56841:60:0;;;;;;;;;;;-1:-1:-1;;56841:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56841:60:0;;-1:-1:-1;56841:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;58019:75::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14878:117::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11741:6;;;;11740:7;11732:16;;;;;;14942:6;:13;;-1:-1:-1;;14942:13:0;14951:4;14942:13;;;14971:16;;;;14942:6;;14971:16;14878:117::o;83180:1251::-;83397:15;;11197:23;:7;11209:10;11197:23;:11;:23;:::i;:::-;11189:32;;;;;;11741:6;;;;11740:7;11732:16;;;;;;83454:12;83446:21;;;;;;83486:22;:42;83515:11;83509:18;;;;;;;;83486:42;;;;;;;;;;;;;;;;;;-1:-1:-1;83486:42:0;;;:51;;;;;;;;;;:60;83478:69;;;;;;83577:1;83566:8;:12;;;:31;;;;;83594:3;83582:8;:15;;;;83566:31;83558:40;;;;;;79706:5;83617:26;:46;83650:11;83644:18;;;;;;;;83617:46;;;;;;;;;;;;;-1:-1:-1;83617:46:0;;;;:78;83609:87;;;;;;83785:22;:42;83814:11;83808:18;;;;;;;;83785:42;;;;;;;;;;;;;-1:-1:-1;83785:42:0;:49;;-1:-1:-1;83855:65:0;83867:6;83785:49;83883:7;83892:11;83905:14;83855:11;:65::i;:::-;83845:75;;83979:22;:42;84008:11;84002:18;;;;;;;;83979:42;;;;;;;;;;;;;;;84041:67;;;;;;;;84051:7;84041:67;;;;84060:6;84041:67;;;;84068:7;84041:67;;;;84077:11;84041:67;;;;;;;;;;;;84090:7;84041:67;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;;-1:-1;83979:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83979:140:0;;;;39:1:-1;83979:140:0;;;;;;;;;;;;;-1:-1:-1;83979:140:0;;;;;;;;;-1:-1:-1;;83979:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84181:26;:46;84214:11;84208:18;;;;;;;;84181:46;;;;;;;;;;;;;;;;-1:-1:-1;84181:46:0;:48;;;;;;;;;-1:-1:-1;;84181:48:0;;;;;;84287:60;;;;;;;;;;;;;84300:7;;84309:6;;84317:11;;84330:7;;84339;;84287:60;;84317:11;84287:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83180:1251;;;;;;;;:::o;57752:79::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;86673:74::-;86741:4;86673:74;:::o;53372:89::-;53446:7;53439:14;;;;;;;;-1:-1:-1;;53439:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53413:13;;53439:14;;53446:7;;53439:14;;53446:7;53439:14;;;;;;;;;;;;;;;;;;;;;;;;13081:158;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;13157:27;:7;13169:14;13157:27;:11;:27;:::i;:::-;13203;:7;13215:14;13203:27;:11;:27;:::i;13870:164::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;13950:28;:6;13961:16;13950:28;:10;:28;:::i;:::-;13997;:6;14008:16;13997:28;:10;:28;:::i;31662:254::-;31748:12;:10;:12::i;:::-;-1:-1:-1;;;;;31742:18:0;:2;-1:-1:-1;;;;;31742:18:0;;;31734:56;;;;;-1:-1:-1;;;31734:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;31842:8;31803:18;:32;31822:12;:10;:12::i;:::-;-1:-1:-1;;;;;31803:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;31803:32:0;;;:36;;;;;;;;;;;;:47;;-1:-1:-1;;31803:47:0;;;;;;;;;;;31881:12;:10;:12::i;:::-;31866:42;;;;;;;;;;-1:-1:-1;;;;;31866:42:0;;;;;;;;;;;;;;31662:254;;:::o;79651:60::-;79706:5;79651:60;:::o;80730:674::-;80857:15;80883:14;80908;80933:21;80965:13;80989;81039:22;:42;81068:11;81062:18;;;;;;;;81039:42;;;;;;;;;;;;;-1:-1:-1;81039:42:0;:49;81029:59;;81021:68;;;;;;81100:26;;:::i;:::-;81129:22;:42;81158:11;81152:18;;;;;;;;81129:42;;;;;;;;;;;;;;;81172:7;81129:51;;;;;;;;;;;;;;;;;;81100:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81213:12;;81240:16;;;;81271;;;;81302:20;;;;81337:16;;;;81368:17;;;;;81213:12;;81240:16;;-1:-1:-1;81271:16:0;;-1:-1:-1;81302:20:0;-1:-1:-1;81337:16:0;;-1:-1:-1;81368:17:0;-1:-1:-1;80730:674:0;-1:-1:-1;;;;80730:674:0:o;74496:681::-;74619:15;74645:14;74670;74695:21;74727:13;74751;74775;74825:18;:38;74850:11;74844:18;;;;;;;;74825:38;;;;;;;;;;;;;-1:-1:-1;74825:38:0;:45;74815:55;;74807:64;;;;;;74882:18;;:::i;:::-;74903;:38;74928:11;74922:18;;;;;;;;74903:38;;;;;;;;;;;;;;;74942:7;74903:47;;;;;;;;;;;;;;;;;;74882:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;74882:68:0;;;-1:-1:-1;;74882:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74983:8;;75006:12;;;;75033;;;;75060:16;;;;75091:12;;;;75118;;;;75145:13;;;;;74983:8;;-1:-1:-1;75006:12:0;;-1:-1:-1;75033:12:0;;-1:-1:-1;75060:16:0;-1:-1:-1;75091:12:0;-1:-1:-1;75118:12:0;;-1:-1:-1;75145:13:0;-1:-1:-1;;74496:681:0;;;;;;;;;;:::o;71972:195::-;72102:8;:15;72056:9;;72091:26;;72083:35;;;;;;72136:8;72145;72136:18;;;;;;;;;;;;;;;;;;;;;:23;;;;;;;;;;-1:-1:-1;;71972:195:0:o;34665:272::-;34780:41;34799:12;:10;:12::i;:::-;34813:7;34780:18;:41::i;:::-;34772:103;;;;-1:-1:-1;;;34772:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34886:43;34904:4;34910:2;34914:7;34923:5;34886:17;:43::i;:::-;34665:272;;;;:::o;58250:58::-;;;;;;;;;;;;;;;:::o;11009:28::-;;;;;;;;;:::o;58882:104::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;73275:60::-;73332:3;73275:60;:::o;88231:222::-;88351:8;:15;88297:17;;88340:26;;88332:35;;;;;;88402:23;;88385:60;;;-1:-1:-1;;;88385:60:0;;;;;;;;;;-1:-1:-1;;;;;88402:23:0;;;;88385:50;;:60;;;;;88402:23;;88385:60;;;;;;;;88402:23;88385:60;;;5:2:-1;;;;30:1;27;20:12;5:2;88385:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88385:60:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;88385:60:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;88385:60:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;-1:-1;;;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;372:25;;-1:-1;88385:60:0;;420:4:-1;411:14;;;;88385:60:0;;;;;411:14:-1;88385:60:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88385:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88378:67;;88231:222;;;:::o;77793:1541::-;78031:15;;11197:23;:7;11209:10;11197:23;:11;:23;:::i;:::-;11189:32;;;;;;11741:6;;;;11740:7;11732:16;;;;;;-1:-1:-1;;;;;78088:20:0;;78080:29;;;;;;78128:12;78120:21;;;;;;78160:22;:42;78189:11;78183:18;;;;;;;;78160:42;;;;;;;;;;;;;;;;;;-1:-1:-1;78160:42:0;;;:51;;;;;;;;;;:60;78152:69;;;;;;78251:1;78240:8;:12;;;:31;;;;;78268:3;78256:8;:15;;;;78240:31;78232:40;;;;;;78283:12;78298:24;:44;78329:11;78323:18;;;;;;;;78298:44;;;;;;;;;;;;;;;:60;78349:7;78343:14;;;;;;;;78298:60;;;;;;;;;;;;;-1:-1:-1;78298:60:0;;;;;;;-1:-1:-1;78373:7:0;:23;;;;;;;;;78369:175;;73264:4;78421:29;;;;78413:38;;;;;;78369:175;;;73332:3;78492:39;;;;78484:48;;;;;;78628:18;:38;78653:11;78647:18;;;;;;;;78628:38;;;;;;;;;;;;;;;:45;;;;78619:54;;78694:61;78706:6;78714;78722:7;78731:11;78744:10;78694:11;:61::i;:::-;78684:71;;78810:26;;:::i;:::-;78847:18;:38;78872:11;78866:18;;;;;;;;78847:38;;;;;;;;;;;;;;;78905:84;;;;;;;;78911:7;78905:84;;;;78920:6;78905:84;;;;78928:7;78905:84;;;;78937:10;78905:84;;;;78949:11;78905:84;;;;;;;;;;;;78962:7;78905:84;;;;;;;;;;;;78971:7;78905:84;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;;-1:-1;78847:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78847:153:0;;;;;;;;;-1:-1:-1;;78847:153:0;;;;;;;;;;;;;;;-1:-1:-1;78847:153:0;;;;;;;;;-1:-1:-1;;78847:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79069:24;:44;79100:11;79094:18;;;;;;;;79069:44;;;;;;;;;;;;;;;:60;79120:7;79114:14;;;;;;;;79069:60;;;;;;;;;;;;;;;;:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79185:65;79194:7;79203:6;79211:11;79224:7;79233;79242;79185:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77793:1541:0;;;;;;;;;:::o;81862:725::-;81954:15;81980:14;82005;82030:21;82062:13;82086;82137:8;:15;;;;82126:8;:26;82118:35;;;;;;82164:22;;:::i;:::-;82189:8;82198;82189:18;;;;;;;;;;;;;;;;;;82164:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82164:43:0;-1:-1:-1;82243:14:0;82226:7;:12;;;:31;;;;;;;;;82218:40;;;;;;82269:26;;:::i;:::-;82298:22;:49;82327:7;:18;;;82321:25;;;;;;;;82298:49;;;;;;;;;;;;;;;82348:7;:14;;;82298:65;;;;;;;32246:147;-1:-1:-1;;;;;32350:25:0;;;32326:4;32350:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;32246:147::o;62575:188::-;62702:6;:13;62652:18;;62691:24;;62683:33;;;;;;62734:6;62741:8;62734:16;;;;;;;;;;;;;;;;;:21;:16;;;;;:21;62727:28;;;;;;;-1:-1:-1;;62727:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62734:21;62727:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62575:188;;;:::o;12622:261::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11922:6;;;;11914:15;;;;;;12112:8;;;;;;;12111:9;12103:18;;;;;;-1:-1:-1;;;;;12736:25:0;;12728:34;;;;;;12773:8;:15;;;-1:-1:-1;;12773:15:0;;;;-1:-1:-1;;;;;;12799:32:0;;-1:-1:-1;;;;;12799:32:0;;;;;;;;;;;;12847:28;;;;;;;;;;;;;;;;;12622:261;:::o;64330:438::-;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;64505:11;60490:18;:38;60515:11;60509:18;;;;;;;;60490:38;;;;;;;;;;;;;-1:-1:-1;60490:38:0;:45;:50;:108;;;;;60544:22;:42;60573:11;60567:18;;;;;;;;60544:42;;;;;;;;;;;;;-1:-1:-1;60544:42:0;:49;:54;60490:108;60482:117;;;;;;64542:25;;;;;:55;;-1:-1:-1;64571:26:0;;;64542:55;64534:64;;;;;;64655:43;;;;;;;;64667:11;64655:43;;;;;;;;;;;;64680:7;;64655:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;;64655:43:0;;;-1:-1:-1;64655:43:0;;;;137:4:-1;64655:43:0;;;;;;;;;;;;;;;;;;;;;;64689:8;;;;;;64655:43;;64689:8;;;;64655:43;1:33:-1;99:1;81:16;;74:27;;;-1:-1;64655:43:0;;;;-1:-1:-1;64609:23:0;;-1:-1:-1;64639:11:0;;-1:-1:-1;64633:18:0;;;;;;;;64609:43;;;;;;;;;;;;;-1:-1:-1;64609:43:0;:89;;;;:43;;-1:-1:-1;;64609:89:0;;;;;;;;;;;;;;;-1:-1:-1;64609:89:0;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;64609:89:0;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;64714:46;64729:11;64742:7;;64751:8;;64714:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;137:4;117:14;-1:-1;;113:30;157:16;;;64714:46:0;;;;;;;;;;;-1:-1:-1;64714:46:0;;;;;1:33:-1;99:1;81:16;;;74:27;64714:46:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;64714:46:0;;;;-1:-1:-1;64714:46:0;;-1:-1:-1;;;;;;;;64714:46:0;11570:1;64330:438;;;;;:::o;65342:1112::-;65683:15;11536:22;65683:15;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;11741:6;;;;11740:7;11732:16;;;;;;65656:11;60490:18;:38;60515:11;60509:18;;;;;;;;60490:38;;;;;;;;;;;;;-1:-1:-1;60490:38:0;:45;:50;:108;;;;;60544:22;:42;60573:11;60567:18;;;;;;;;60544:42;;;;;;;;;;;;;-1:-1:-1;60544:42:0;:49;:54;60490:108;60482:117;;;;;;65724:18;65716:27;;;;;;65762:23;65754:32;;;;;;65805:22;65797:31;;;;;;65876:6;:13;;;;65866:23;;65937:6;65963:87;;;;;;;;65969:7;65963:87;;;;65978:11;65963:87;;;;;;;;;;;;65991:7;65963:87;;;;;;;;;;;;66000:5;65963:87;;;;;;;;;;;;66007:7;65963:87;;;;;;;;;;;;66016:10;65963:87;;;;;;66029:7;;65963:87;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;;65963:87:0;;;-1:-1:-1;65963:87:0;;;;137:4:-1;65963:87:0;;;;;;;;;;;;;;;;;;;;;;66038:5;;;;;;65963:87;;66038:5;;;;65963:87;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;;65963:87:0;;;-1:-1:-1;65963:87:0;;;;137:4:-1;65963:87:0;;;;;;;;;;;;;;;;;;;;;;66045:4;;;;;;65963:87;;66045:4;;;;65963:87;1:33:-1;99:1;81:16;;74:27;;;-1:-1;65963:87:0;;;;-1:-1:-1;;27:10;;39:1;23:18;;;45:23;;;65937:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65937:124:0;;;;-1:-1:-1;;65937:124:0;;;;;;;;;;;;;;;-1:-1:-1;65937:124:0;;;;;;;;;-1:-1:-1;;65937:124:0;;;;;;;;;;;;;;;-1:-1:-1;65937:124:0;;;;;;;;;-1:-1:-1;;65937:124:0;;;;;;;;;;;;;;;-1:-1:-1;65937:124:0;;;;;;;;;-1:-1:-1;;65937:124:0;;;;;;;;;;;;;;;-1:-1:-1;65937:124:0;;;;;;;;;;;;;-1:-1:-1;;;65937:124:0;-1:-1:-1;;65937:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;65937:124:0;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;65937:124:0;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;66257:7;66166:35;:55;66208:11;66202:18;;;;;;;;66166:55;;;;;;;;;;;;;;;:69;66228:5;66222:12;;;;;;;;66166:69;;;;;;;;;;;;;;;:88;66242:10;66166:88;;;;;;;;;;;;;;;:98;;;;66318:65;66327:7;66336:11;66349:5;66356:7;66365:10;66377:5;;66318:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;66318:65:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;66318:65:0;;;;-1:-1:-1;66318:65:0;;-1:-1:-1;;;;;;;;;66318:65:0;11759:1;65342:1112;;;;;;;;;;;;;:::o;61770:637::-;61857:10;61878:21;61910:22;61943:13;61967:9;61987:13;62011:15;62037:18;62093:6;:13;;;;62082:8;:24;62074:33;;;;;;62118:18;;:::i;:::-;62139:6;62146:8;62139:16;;;;;;;;;;;;;;;;;;62118:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;62118:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;62118:37:0;;;-1:-1:-1;;62118:37:0;;;;;;;;;;;;;;;;-1:-1:-1;;62118:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;62118:37:0;;;-1:-1:-1;;62118:37:0;;;;;;;;;;;;;;;;-1:-1:-1;;62118:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62188:5;:8;;;62211:5;:16;;;62242:5;:12;;;62269:5;:12;;;62296:5;:10;;;62321:5;:12;;;62348:5;:15;;;62378:5;:10;;;62166:233;;;;;;;;;;;;;;;;;;;;;;;61770:637;;;;;;;;;:::o;57368:72::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;63003:234::-;63092:17;11536:22;:6;11547:10;11536:22;:10;:22;:::i;:::-;11528:31;;;;;;63141:6;:13;63130:24;;63122:33;;;;;;63166:18;;:::i;:::-;63187:6;63194:8;63187:16;;;;;;;;;;;;;;;;;;63166:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63166:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63166:37:0;;;-1:-1:-1;;63166:37:0;;;;;;;;;;;;;;;;-1:-1:-1;;63166:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63166:37:0;;;-1:-1:-1;;63166:37:0;;;;;;;;;;;;;;;;-1:-1:-1;;63166:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63166:37:0;;;;-1:-1:-1;;;63220:9:0;;;;63003:234;-1:-1:-1;;;63003:234:0:o;36130:155::-;36187:4;36220:20;;;:11;:20;;;;;;-1:-1:-1;;;;;36220:20:0;36258:19;;;36130:155::o;16109:98::-;16189:10;16109:98;:::o;3064:183::-;3151:20;3223:2;3234;3200:38;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;3200:38:0;;;;;;;;;;-1:-1:-1;3200:38:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;3200:38:0;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3200:38:0;;;3184:55;;3064:183;;;;:::o;36655:333::-;36740:4;36765:16;36773:7;36765;:16::i;:::-;36757:73;;;;-1:-1:-1;;;36757:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36841:13;36857:16;36865:7;36857;:16::i;:::-;36841:32;;36903:5;-1:-1:-1;;;;;36892:16:0;:7;-1:-1:-1;;;;;36892:16:0;;:51;;;;36936:7;-1:-1:-1;;;;;36912:31:0;:20;36924:7;36912:11;:20::i;:::-;-1:-1:-1;;;;;36912:31:0;;36892:51;:87;;;;36947:32;36964:5;36971:7;36947:16;:32::i;45838:245::-;45924:38;45944:4;45950:2;45954:7;45924:19;:38::i;:::-;45975:47;46008:4;46014:7;45975:32;:47::i;:::-;46035:40;46063:2;46067:7;46035:27;:40::i;67441:1586::-;67543:17;67599:1;67586:10;:14;67578:23;;;;;;67612:25;:182;;;;;;;;;;;;;;;;;;-1:-1:-1;67825:3:0;67858;67805:17;;;;;68016:18;;:::i;:::-;68117:10;68112:856;68147:15;68133:30;;;;68112:856;;68212:15;;;;;68280:25;;;;-1:-1:-1;68370:20:0;;;;-1:-1:-1;68212:15:0;-1:-1:-1;68451:16:0;;68447:510;;68508:1;68501:4;:8;;;68500:156;;68644:12;68500:156;;;68606:14;68591:12;:29;;;;;;68500:156;68488:168;-1:-1:-1;68679:13:0;;68675:267;;68727:35;:55;68769:11;68763:18;;;;;;;;68727:55;;;;;;;;;;;;;;;;;;-1:-1:-1;68727:55:0;;;:61;;;;;;;;;;:79;;;;;;;;;;68837:6;:15;;68727:79;;-1:-1:-1;68837:6:0;68727:79;;68837:15;;;;;;;;;;;;;;;;68829:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;68829:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;68829:23:0;;;-1:-1:-1;;68829:23:0;;;;;;;;;;;;;;;;-1:-1:-1;;68829:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;68829:23:0;;;-1:-1:-1;;68829:23:0;;;;;;;;;;;;;;;;-1:-1:-1;;68829:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68889:33;68899:11;68912:5;:9;;;68889;:33::i;:::-;68875:47;;68675:267;68165:6;;68112:856;;;;68987:32;68997:11;68987:32;;;;;;;;;;;;;-1:-1:-1;;;68987:32:0;;;:9;:32::i;:::-;68980:39;67441:1586;-1:-1:-1;;;;;;;;;;;;67441:1586:0:o;4119:203::-;4191:4;-1:-1:-1;;;;;4216:21:0;;4208:68;;;;-1:-1:-1;;;4208:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;4294:20:0;:11;:20;;;;;;;;;;;;;;;4119:203::o;3841:183::-;3921:18;3925:4;3931:7;3921:3;:18::i;:::-;3913:64;;;;-1:-1:-1;;;3913:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3988:20:0;4011:5;3988:20;;;;;;;;;;;:28;;-1:-1:-1;;3988:28:0;;;3841:183::o;3583:178::-;3661:18;3665:4;3671:7;3661:3;:18::i;:::-;3660:19;3652:63;;;;;-1:-1:-1;;;3652:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3726:20:0;:11;:20;;;;;;;;;;;:27;;-1:-1:-1;;3726:27:0;3749:4;3726:27;;;3583:178::o;24874:114::-;24966:14;;24874:114::o;70196:1583::-;11741:6;;70397:15;;11741:6;;11740:7;11732:16;;;;;;70533:32;:52;70572:11;70566:18;;;;;;;;70533:52;;;;;;;;;;;;;;;:66;70592:5;70586:12;;;;;;;;70533:66;;;;;;;;;;;;;;;;-1:-1:-1;70533:66:0;;;:75;;;;;;;;;:80;70525:89;;;;;;70754:10;70745:5;:19;;;;;;;;;70741:218;;;70799:18;:38;70824:11;70818:18;;;;;;;;70799:38;;;;;;;;;;;;;-1:-1:-1;70799:38:0;:45;70788:56;;70780:65;;;;;;70741:218;;;70897:22;:42;70926:11;70920:18;;;;;;;;70897:42;;;;;;;;;;;;;-1:-1:-1;70897:42:0;:49;70886:60;;70878:69;;;;;;-1:-1:-1;71006:8:0;:15;71077:22;;:::i;:::-;71102:54;;;;;;;;71110:7;71102:54;;;;71119:7;71102:54;;;;71128:7;71102:54;;;;71137:11;71102:54;;;;;;;;;;;;71150:5;71102:54;;;;;;;;;;71199:8;27:10:-1;;39:1;23:18;;;45:23;;;-1:-1;71199:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71077:79;;-1:-1:-1;23:18;;71077:79:0;;71199:22;;;;-1:-1:-1;;71199:22:0;;;;;;;;;;;;;;;;;-1:-1:-1;71199:22:0;;;;;;;;;-1:-1:-1;;71199:22:0;;;;;;;;;;;;;;;;;;;71365:4;71297:22;:49;71326:7;:18;;;71320:25;;;;;;;;71297:49;;;;;;;;;;;;;;;;-1:-1:-1;71297:49:0;;;71347:14;;;;71297:65;;;;;;;:72;;-1:-1:-1;;71297:72:0;;;;;;;;;;;71510:10;;71471:18;;;;71510:10;;71438:26;;71465:25;;;;;;;;71438:53;;;;;;;;;;;;;;;:69;71492:7;:14;;;71438:69;;;;;;;;;;;:82;;;;71693:7;:10;;;71594:32;:59;71633:7;:18;;;71627:25;;;;;;;;71594:59;;;;;;;;;;;;;;;:80;71660:7;:12;;;71654:19;;;;;;;;71594:80;;;;;;;;;;;;;;;;-1:-1:-1;71594:80:0;;;71675:14;;;;71594:96;;;;;;;:109;71743:28;71755:6;71763:7;71743:11;:28::i;:::-;11759:1;70196:1583;;;;;;;:::o;35656:272::-;35766:32;35780:4;35786:2;35790:7;35766:13;:32::i;:::-;35817:48;35840:4;35846:2;35850:7;35859:5;35817:22;:48::i;:::-;35809:111;;;;-1:-1:-1;;;35809:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40351:459;40465:4;-1:-1:-1;;;;;40445:24:0;:16;40453:7;40445;:16::i;:::-;-1:-1:-1;;;;;40445:24:0;;40437:78;;;;-1:-1:-1;;;40437:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40534:16:0;;40526:65;;;;-1:-1:-1;;;40526:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40604:23;40619:7;40604:14;:23::i;:::-;-1:-1:-1;;;;;40640:23:0;;;;;;:17;:23;;;;;:35;;:33;:35::i;:::-;-1:-1:-1;;;;;40686:21:0;;;;;;:17;:21;;;;;:33;;:31;:33::i;:::-;40732:20;;;;:11;:20;;;;;;:25;;-1:-1:-1;;;;;;40732:25:0;-1:-1:-1;;;;;40732:25:0;;;;;;;;;40775:27;;40732:20;;40775:27;;;;;;;40351:459;;;:::o;49023:1148::-;-1:-1:-1;;;;;49314:18:0;;49289:22;49314:18;;;:12;:18;;;;;:25;:32;;49344:1;49314:32;:29;:32;:::i;:::-;49357:18;49378:26;;;:17;:26;;;;;;49289:57;;-1:-1:-1;49511:28:0;;;49507:328;;-1:-1:-1;;;;;49578:18:0;;49556:19;49578:18;;;:12;:18;;;;;:34;;49597:14;;49578:34;;;;;;;;;;;;;;49556:56;;49662:11;49629:12;:18;49642:4;-1:-1:-1;;;;;49629:18:0;-1:-1:-1;;;;;49629:18:0;;;;;;;;;;;;49648:10;49629:30;;;;;;;;;;;;;;;;;;;:44;;;;49746:30;;;:17;:30;;;;;:43;;;49507:328;-1:-1:-1;;;;;49924:18:0;;;;;;:12;:18;;;;;:27;;;;;-1:-1:-1;;49924:27:0;;;:::i;:::-;;49023:1148;;;;:::o;47845:186::-;-1:-1:-1;;;;;47959:16:0;;;;;;;:12;:16;;;;;;;;:23;;47930:26;;;:17;:26;;;;;:52;;;47993:16;;;39:1:-1;23:18;;45:23;;47993:30:0;;;;;;;;47845:186::o;46348:202::-;46412:24;46424:2;46428:7;46412:11;:24::i;:::-;46449:40;46477:2;46481:7;46449:27;:40::i;:::-;46502;46534:7;46502:31;:40::i;41412:358::-;41534:4;41561:15;:2;-1:-1:-1;;;;;41561:13:0;;:15::i;:::-;41556:60;;-1:-1:-1;41600:4:0;41593:11;;41556:60;41628:13;41660:2;-1:-1:-1;;;;;41644:36:0;;41681:12;:10;:12::i;:::-;41695:4;41701:7;41710:5;41644:72;;;;;;;;;;;;;-1:-1:-1;;;;;41644:72:0;-1:-1:-1;;;;;41644:72:0;;;;;;-1:-1:-1;;;;;41644:72:0;-1:-1:-1;;;;;41644:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;41644:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41644:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41644:72:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41644:72:0;-1:-1:-1;;;;;;41735:26:0;-1:-1:-1;;;41735:26:0;;-1:-1:-1;;41412:358:0;;;;;;:::o;41938:175::-;42038:1;42002:24;;;:15;:24;;;;;;-1:-1:-1;;;;;42002:24:0;:38;41998:108;;42092:1;42057:24;;;:15;:24;;;;;:37;;-1:-1:-1;;;;;;42057:37:0;;;41938:175::o;25095:110::-;25176:14;;:21;;25195:1;25176:21;:18;:21;:::i;:::-;25159:38;;25095:110::o;24996:91::-;25060:19;;25078:1;25060:19;;;24996:91::o;5698:136::-;5756:7;5783:43;5787:1;5790;5783:43;;;;;;;;;;;;;;;;;:3;:43::i;38740:335::-;-1:-1:-1;;;;;38812:16:0;;38804:61;;;;;-1:-1:-1;;;38804:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38885:16;38893:7;38885;:16::i;:::-;38884:17;38876:58;;;;;-1:-1:-1;;;38876:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38947:20;;;;:11;:20;;;;;;;;:25;;-1:-1:-1;;;;;;38947:25:0;-1:-1:-1;;;;;38947:25:0;;;;;;;;38983:21;;:17;:21;;;;;:33;;:31;:33::i;:::-;39034;;39059:7;;-1:-1:-1;;;;;39034:33:0;;;39051:1;;39034:33;;39051:1;;39034:33;38740:335;;:::o;48232:164::-;48336:10;:17;;48309:24;;;;:15;:24;;;;;:44;;;39:1:-1;23:18;;45:23;;48364:24:0;;;;;;;48232:164::o;21251:810::-;21311:4;21970:20;;21813:66;22010:15;;;;;:42;;-1:-1:-1;22029:23:0;;;21251:810;-1:-1:-1;;21251:810:0:o;6171:192::-;6257:7;6293:12;6285:6;;;;6277:29;;;;-1:-1:-1;;;6277:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6277:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6329:5:0;;;6171:192::o;85436:6574::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;85436:6574:0;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;85436:6574:0;;;-1:-1:-1;;85436:6574:0:o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85436:6574:0;;;-1:-1:-1;85436:6574:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85436:6574:0;;;-1:-1:-1;85436:6574:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85436:6574:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;85436:6574:0;;;;;;

Swarm Source

bzzr://58dc70ca79f03c655381e9b8ffb65b62e19238f259a0093e34ed6dde4d524ae8
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.