ETH Price: $3,184.73 (+3.19%)

Token

AI43 Strings (STRING)
 

Overview

Max Total Supply

4,551 STRING

Holders

1,032

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 STRING
0xf2b15320db6992ba49a7563e50e888c20edcbe3c
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

AI generating NFT collectibles for Humans.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
StringsToken

Compiler Version
v0.8.1+commit.df193b15

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Multiple files format)

File 18 of 18: StringToken.sol
pragma solidity ^0.8.1;

//   █████ ██ ██ ██   ██  ███████
//   ██    ██ ██ ██   ██       ██           ███ ███ █ ██ ███ ███ ███ ███ ███
//   ██ █████ ██ ██ █████ ████ ██           █   █ █ █ ██  █  █ █ █ █ █    █
//   ██    ██ ██      ██       ██           █   █ █ ██ █  █  ██  ███ █    █
//   ██    ██ ██      ██  ████ ██   STRING  ███ ███ █  █  █  █ █ █ █ ███  █
 
import "./Address.sol";
import "./EnumerableMap.sol";
import "./EnumerableSet.sol";
import "./SafeMath.sol";
import "./Context.sol";
import "./Ownable.sol";
import "./Strings.sol";

import "./IERC165.sol";
import "./ERC165Storage.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Metadata.sol";
import "./IERC721Receiver.sol";
import "./IERC20.sol";
import "./IDUST.sol";

/**
 * @dev StringsToken (a ERC721 non-fungible token)
 */
contract StringsToken is Context, Ownable, ERC165Storage, IERC721Enumerable, IERC721Metadata {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;

    // STRINGS can be minted for DUST
    uint256 public constant STRING_MINT_PRICE_S1 =  512000000000000000000;
    uint256 public constant STRING_MINT_PRICE_S2 = 1024000000000000000000;
    uint256 public constant STRING_MINT_PRICE_S3 = 2048000000000000000000;

    // 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 holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSet.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMap.UintToAddressMap private _tokenOwners;

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

    // Mapping from token ID to name
    mapping (uint256 => string) private _tokenName;

    // Mapping from token ID to name
    mapping (uint256 => uint256) private _tokenSeed;

    // Seed already used ? times 16
    mapping (uint256 => bool) private _seedUsed;

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // DUST Token address
    address private _dustAddress;

    // Number of burned strings
    uint256 private _burnedStrings;

    // Number of max strings
    uint256 private _maxSupply;

    /*
     *     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 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

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

    /*
     *     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;

    // Events
    event MintedStrings(address minter, uint256 stringId, uint256 count, uint256 dustAmount, uint256 seed);
    event DestroyedString(uint256 indexed stringId, address destroyer, string lastWords);
    event ChangedStringName(uint256 tokenId, string newName);

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor (string memory cname, string memory csymbol, address dustAddress) {
        _name = cname;
        _symbol = csymbol;
        _dustAddress = dustAddress;
        _burnedStrings = 0;
	_maxSupply = 11111;

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

    /**
     * @dev Returns base token URI 
     */
    function baseTokenURI() public pure returns (string memory) {
        return "https://app.ai43.art/api/string/";
    }

    /**
     * @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));
      return string(abi.encodePacked(baseTokenURI(), Strings.toString(tokenId)));
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        return _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

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

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _tokenOwners.length().sub(_burnedStrings);
    }

    function mintedSupply() public view returns (uint256) {
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

    /**
     * @dev Returns name of the NFT at index.
     */
    function tokenNameByIndex(uint256 index) public view returns (string memory) {
        return _tokenName[index];
    }

    /**
     * @dev Returns seed of the NFT at index.
     */
    function tokenSeedByIndex(uint256 index) public view returns (uint256) {
        return _tokenSeed[index];
    }
    
    /**
     * @dev Returns if the seed is free 
     */
    function isSeedFree(uint256 seed) public view returns (bool) {
	return (_seedUsed[seed] == false);	
    }

    /**
    * @dev Buy a String with Dust
    */
    function mintString(uint256 dustAmount, uint256 seed) public {
	require(_seedUsed[seed] == false, "seed used alredy");
        require((dustAmount == STRING_MINT_PRICE_S1) || (dustAmount == STRING_MINT_PRICE_S2) || (dustAmount == STRING_MINT_PRICE_S3), "dustAmount not correct");
        require(_maxSupply >= mintedSupply().add(1), "Not enough Strings left");
	require(seed < 18446744073709551599, "seed max 8 bytes");

        IDUST(_dustAddress).transferFrom(msg.sender, address(this), dustAmount);
        IDUST(_dustAddress).burn(dustAmount.mul(80).div(100)); // burn 80% of the dust, keep 20% as treasury for incentives, puzzles etc.

	uint mintStart = mintedSupply();
        _safeMint(msg.sender, mintStart);
	_seedUsed[seed] = true;
	_tokenSeed[mintStart] = seed;

        emit MintedStrings(msg.sender, mintStart, 1, dustAmount, seed);
    }

    /**
    * @dev Buy multiple Strings with Dust
    */
    function mintStrings(uint256 count, uint256 dustAmount, uint256 startSeed) public {
        require((dustAmount == STRING_MINT_PRICE_S1) || (dustAmount == STRING_MINT_PRICE_S2) || (dustAmount == STRING_MINT_PRICE_S3), "dustAmount not correct");
	require(count < 17, "maximum of 16 Strings at once");
        require(_maxSupply >= mintedSupply().add(count), "Not enough Strings left");
	require(startSeed < 18446744073709551599, "seed max 8 bytes");

        IDUST(_dustAddress).transferFrom(msg.sender, address(this), dustAmount.mul(count));
        IDUST(_dustAddress).burn(dustAmount.mul(count).mul(80).div(100)); // burn 80% of the dust, keep 20% as treasury for incentives, puzzles etc.

	uint mintStart = mintedSupply();
        for (uint i = 0; i < count; i++) {
	    require(_seedUsed[startSeed+i] == false, "seed already used, use another start");
            _safeMint(msg.sender, mintedSupply());
	    _seedUsed[startSeed+i] = true;
	    _tokenSeed[mintStart] = startSeed+i;
        }
        emit MintedStrings(msg.sender, mintStart, count, dustAmount, startSeed);
    }

    /**
    * @dev Rename a String, for free
    */
    function changeStringName(uint256 tokenId, string memory newName) external {
        require(_msgSender() == ownerOf(tokenId), "ERC721: caller is not the owner");
        require(checkName(newName) == true, "ERROR: name does not follow rules");
        require(keccak256(bytes(newName)) != keccak256(bytes(_tokenName[tokenId])), "ERROR: name is the same");

        _tokenName[tokenId] = newName;
        emit ChangedStringName(tokenId, newName);
    }

    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     * - Last words must be supplied.
     */
    function burn(uint256 tokenId, string memory lastWords) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
        require(checkName(lastWords) == true, "ERROR: name does not follow rules");
        _tokenName[tokenId] = lastWords;
        _burn(tokenId);
	emit DestroyedString(tokenId, _msgSender(), lastWords);
    }

    /**
     * @dev Withdraw ether from this contract (Callable by owner)
    */
    function changeMaxSupply(uint256 max) external onlyOwner {
        _maxSupply = max;
    }

    /**
     * @dev Withdraw ether from this contract (Callable by owner)
    */
    function withdraw() external onlyOwner {
        address payable ownerPay = payable(owner());
        ownerPay.transfer(address(this).balance);
    }

    /**
     * @dev Withdraw DUST from this contract for incentives (Callable by owner)
    */
    function withdrawDUST(uint256 amount) external onlyOwner {
        IERC20(_dustAddress).transfer(owner(), amount);
    }

    /**
     * @dev Withdraw stuck ERC20s from this contract (Callable by owner)
    */
    function withdrawStuckERC20(address token, uint256 amount) external onlyOwner {
        require(token != _dustAddress, 'ERROR: cannot remove dust tokens');
        IERC20(token).transfer(owner(), amount);
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        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"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

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

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return _tokenOwners.contains(tokenId);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    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 Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     d*
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

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

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.set(tokenId, address(0));

	_burnedStrings++;

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

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(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.
     *
     * @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)
        private returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }
        bytes memory returndata = to.functionCall(abi.encodeWithSelector(
            IERC721Receiver(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ), "ERC721: transfer to non ERC721Receiver implementer");
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == _ERC721_RECEIVED);
    }

    function _approve(address to, uint256 tokenId) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }

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

    /**
     * @dev check if name is valid (ascii range 0x20-0x7E without leading/trailing spaces)
     */
    function checkName(string memory str) public pure returns (bool){
        bytes memory b = bytes(str);
        if (b.length == 0) return false; // not empty
        if (b.length > 24) return false; // max 24 chars 
        if (b[0] == 0x20) return false;  // no leading space
        if (b[b.length - 1] == 0x20) return false; // no trailing space

        for(uint i; i < b.length; i++) { // asci range 0x20 to 0x7E
	    if (b[i] > 0x7E || b[i] < 0x20)
		return false;
        }
        return true;
    }
}


File 1 of 18: Address.sol
// SPDX-License-Identifier: MIT
// from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

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

File 2 of 18: Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.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 meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

File 3 of 18: EnumerableMap.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./EnumerableSet.sol";

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
 * supported.
 */
library EnumerableMap {
    using EnumerableSet for EnumerableSet.Bytes32Set;

    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct Map {
        // Storage of keys
        EnumerableSet.Bytes32Set _keys;

        mapping (bytes32 => bytes32) _values;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
        map._values[key] = value;
        return map._keys.add(key);
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function _remove(Map storage map, bytes32 key) private returns (bool) {
        delete map._values[key];
        return map._keys.remove(key);
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function _contains(Map storage map, bytes32 key) private view returns (bool) {
        return map._keys.contains(key);
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function _length(Map storage map) private view returns (uint256) {
        return map._keys.length();
    }

   /**
    * @dev Returns the key-value pair stored at position `index` in the map. O(1).
    *
    * Note that there are no guarantees on the ordering of entries inside the
    * array, and it may change when more entries are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
        bytes32 key = map._keys.at(index);
        return (key, map._values[key]);
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
        bytes32 value = map._values[key];
        if (value == bytes32(0)) {
            return (_contains(map, key), bytes32(0));
        } else {
            return (true, value);
        }
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        bytes32 value = map._values[key];
        require(value != 0 || _contains(map, key), "EnumerableMap: nonexistent key");
        return value;
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {_tryGet}.
     */
    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
        bytes32 value = map._values[key];
        require(value != 0 || _contains(map, key), errorMessage);
        return value;
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
        return _remove(map._inner, bytes32(key));
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
        return _contains(map._inner, bytes32(key));
    }

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToAddressMap storage map) internal view returns (uint256) {
        return _length(map._inner);
    }

   /**
    * @dev Returns the element stored at position `index` in the set. O(1).
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        return (uint256(key), address(uint160(uint256(value))));
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     *
     * _Available since v3.4._
     */
    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
        return (success, address(uint160(uint256(value))));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
    }
}

File 4 of 18: EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 5 of 18: ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 6 of 18: ERC165Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC165.sol";

/**
 * @dev Storage based implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165Storage is ERC165 {
    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return super.supportsInterface(interfaceId) || _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 virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}


File 7 of 18: ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./Context.sol";

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The defaut value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

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

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

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        return true;
    }

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

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

        return true;
    }

    function burn(uint256 amount) public virtual override returns (bool) {
        _burn(_msgSender(), amount);
        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

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

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

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

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _balances[account] = accountBalance - amount;
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);
    }

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

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

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

File 8 of 18: IDUST.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

    /**
     * allows dust to be burned...
     */
    function burn(uint256 amount) external returns (bool);

    /**
     * and minted
     */
    function mint(address to, uint256 amount) external returns (bool);

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

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

File 9 of 18: IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.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 10 of 18: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

    /**
     * allows dust to be burned...
     */
    function burn(uint256 amount) external returns (bool);

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

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

File 11 of 18: IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

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

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
      * - `from` cannot be the zero address.
      * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

File 12 of 18: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {

    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 13 of 18: IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {

    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    //function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 14 of 18: IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

File 15 of 18: Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

File 16 of 18: SafeMath.sol
// SPDX-License-Identifier: MIT
// from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol
pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // 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 (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @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) {
        return a + b;
    }

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

    /**
     * @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) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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 a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards 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).
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 17 of 18: Strings.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Strings {
  /**
    * @dev Converts a `uint256` to its ASCII `string` decimal representation.
    */
   function toString(uint256 value) internal pure returns (string memory) {
       // Inspired by OraclizeAPI's implementation - MIT licence
       // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

       if (value == 0) {
           return "0";
       }
       uint256 temp = value;
       uint256 digits;
       while (temp != 0) {
           digits++;
           temp /= 10;
       }
       bytes memory buffer = new bytes(digits);
       while (value != 0) {
           digits -= 1;
           buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
           value /= 10;
       }
       return string(buffer);
   }
}


Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"cname","type":"string"},{"internalType":"string","name":"csymbol","type":"string"},{"internalType":"address","name":"dustAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"newName","type":"string"}],"name":"ChangedStringName","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stringId","type":"uint256"},{"indexed":false,"internalType":"address","name":"destroyer","type":"address"},{"indexed":false,"internalType":"string","name":"lastWords","type":"string"}],"name":"DestroyedString","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"stringId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dustAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"seed","type":"uint256"}],"name":"MintedStrings","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":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"},{"inputs":[],"name":"STRING_MINT_PRICE_S1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRING_MINT_PRICE_S2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRING_MINT_PRICE_S3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"lastWords","type":"string"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"}],"name":"changeMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newName","type":"string"}],"name":"changeStringName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"checkName","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"seed","type":"uint256"}],"name":"isSeedFree","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dustAmount","type":"uint256"},{"internalType":"uint256","name":"seed","type":"uint256"}],"name":"mintString","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"uint256","name":"dustAmount","type":"uint256"},{"internalType":"uint256","name":"startSeed","type":"uint256"}],"name":"mintStrings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenNameByIndex","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenSeedByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawDUST","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawStuckERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162005a3e38038062005a3e8339818101604052810190620000379190620003d5565b600062000049620001bc60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35082600b9080519060200190620000ff9291906200029c565b5081600c9080519060200190620001189291906200029c565b5080600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600e81905550612b67600f81905550620001836380ac58cd60e01b620001c460201b60201c565b6200019b635b5e139f60e01b620001c460201b60201c565b620001b363780e9d6360e01b620001c460201b60201c565b5050506200069e565b600033905090565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141562000230576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002279062000484565b60405180910390fd5b6001806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b828054620002aa9062000580565b90600052602060002090601f016020900481019282620002ce57600085556200031a565b82601f10620002e957805160ff19168380011785556200031a565b828001600101855582156200031a579182015b8281111562000319578251825591602001919060010190620002fc565b5b5090506200032991906200032d565b5090565b5b80821115620003485760008160009055506001016200032e565b5090565b6000620003636200035d84620004cf565b620004a6565b9050828152602081018484840111156200037c57600080fd5b620003898482856200054a565b509392505050565b600081519050620003a28162000684565b92915050565b600082601f830112620003ba57600080fd5b8151620003cc8482602086016200034c565b91505092915050565b600080600060608486031215620003eb57600080fd5b600084015167ffffffffffffffff8111156200040657600080fd5b6200041486828701620003a8565b935050602084015167ffffffffffffffff8111156200043257600080fd5b6200044086828701620003a8565b9250506040620004538682870162000391565b9150509250925092565b60006200046c601c8362000505565b915062000479826200065b565b602082019050919050565b600060208201905081810360008301526200049f816200045d565b9050919050565b6000620004b2620004c5565b9050620004c08282620005b6565b919050565b6000604051905090565b600067ffffffffffffffff821115620004ed57620004ec6200061b565b5b620004f8826200064a565b9050602081019050919050565b600082825260208201905092915050565b600062000523826200052a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156200056a5780820151818401526020810190506200054d565b838111156200057a576000848401525b50505050565b600060028204905060018216806200059957607f821691505b60208210811415620005b057620005af620005ec565b5b50919050565b620005c1826200064a565b810181811067ffffffffffffffff82111715620005e357620005e26200061b565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4552433136353a20696e76616c696420696e7465726661636520696400000000600082015250565b6200068f8162000516565b81146200069b57600080fd5b50565b61539080620006ae6000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c8063715018a611610125578063b88d4fde116100ad578063cb67e96d1161007c578063cb67e96d14610637578063d547cfb714610655578063e8d01cf014610673578063e985e9c5146106a3578063f2fde38b146106d35761021c565b8063b88d4fde146105b1578063c1bd8cf9146105cd578063c275683d146105eb578063c87b56dd146106075761021c565b80638b456d0b116100f45780638b456d0b1461050b5780638da5cb5b1461053b57806395d89b4114610559578063a22cb46514610577578063b87cc30f146105935761021c565b8063715018a6146104ab57806374dec154146104b55780637641e6f3146104d35780637aad0446146104ef5761021c565b80633ccfd60b116101a85780635cdd776f116101775780635cdd776f146103e357806362e21487146103ff5780636352211e1461041b5780636d5224181461044b57806370a082311461047b5761021c565b80633ccfd60b14610371578063404c7cdd1461037b57806342842e0e146103975780634f6ccce7146103b35761021c565b80631400d1e4116101ef5780631400d1e4146102bb57806318160ddd146102eb57806323b872dd146103095780632c58bb88146103255780632f745c59146103415761021c565b806301ffc9a71461022157806306fdde0314610251578063081812fc1461026f578063095ea7b31461029f575b600080fd5b61023b60048036038101906102369190613a87565b6106ef565b6040516102489190614374565b60405180910390f35b610259610767565b604051610266919061438f565b60405180910390f35b61028960048036038101906102849190613b1a565b6107f9565b60405161029691906141d7565b60405180910390f35b6102b960048036038101906102b49190613a22565b61087e565b005b6102d560048036038101906102d09190613ad9565b610996565b6040516102e29190614374565b60405180910390f35b6102f3610be2565b6040516103009190614731565b60405180910390f35b610323600480360381019061031e919061391c565b610c07565b005b61033f600480360381019061033a9190613a22565b610c67565b005b61035b60048036038101906103569190613a22565b610e0d565b6040516103689190614731565b60405180910390f35b610379610e68565b005b61039560048036038101906103909190613b1a565b610f3a565b005b6103b160048036038101906103ac919061391c565b610fc0565b005b6103cd60048036038101906103c89190613b1a565b610fe0565b6040516103da9190614731565b60405180910390f35b6103fd60048036038101906103f89190613b1a565b611003565b005b61041960048036038101906104149190613b43565b611139565b005b61043560048036038101906104309190613b1a565b6112db565b60405161044291906141d7565b60405180910390f35b61046560048036038101906104609190613b1a565b611312565b604051610472919061438f565b60405180910390f35b610495600480360381019061049091906138b7565b6113b7565b6040516104a29190614731565b60405180910390f35b6104b3611476565b005b6104bd6115b0565b6040516104ca9190614731565b60405180910390f35b6104ed60048036038101906104e89190613b43565b6115bd565b005b61050960048036038101906105049190613bd3565b6116d2565b005b61052560048036038101906105209190613b1a565b611b25565b6040516105329190614731565b60405180910390f35b610543611b42565b60405161055091906141d7565b60405180910390f35b610561611b6b565b60405161056e919061438f565b60405180910390f35b610591600480360381019061058c91906139e6565b611bfd565b005b61059b611d7e565b6040516105a89190614731565b60405180910390f35b6105cb60048036038101906105c6919061396b565b611d8b565b005b6105d5611ded565b6040516105e29190614731565b60405180910390f35b61060560048036038101906106009190613b97565b611dfe565b005b610621600480360381019061061c9190613b1a565b6121a4565b60405161062e919061438f565b60405180910390f35b61063f6121f0565b60405161064c9190614731565b60405180910390f35b61065d6121fd565b60405161066a919061438f565b60405180910390f35b61068d60048036038101906106889190613b1a565b61223a565b60405161069a9190614374565b60405180910390f35b6106bd60048036038101906106b891906138e0565b61226a565b6040516106ca9190614374565b60405180910390f35b6106ed60048036038101906106e891906138b7565b6122fe565b005b60006106fa826124a7565b80610760575060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff165b9050919050565b6060600b805461077690614a43565b80601f01602080910402602001604051908101604052809291908181526020018280546107a290614a43565b80156107ef5780601f106107c4576101008083540402835291602001916107ef565b820191906000526020600020905b8154815290600101906020018083116107d257829003601f168201915b5050505050905090565b600061080482612511565b610843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083a906145d1565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610889826112db565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156108fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f190614651565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661091961252e565b73ffffffffffffffffffffffffffffffffffffffff16148061094857506109478161094261252e565b61226a565b5b610987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097e90614531565b60405180910390fd5b6109918383612536565b505050565b6000808290506000815114156109b0576000915050610bdd565b6018815111156109c4576000915050610bdd565b602060f81b81600081518110610a03577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a40576000915050610bdd565b602060f81b8160018351610a549190614947565b81518110610a8b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610ac8576000915050610bdd565b60005b8151811015610bd657607e60f81b828281518110610b12577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161180610bb35750602060f81b828281518110610b84577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916105b15610bc357600092505050610bdd565b8080610bce90614aa6565b915050610acb565b5060019150505b919050565b6000610c02600e54610bf460036125ef565b61260490919063ffffffff16565b905090565b610c18610c1261252e565b8261261a565b610c57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4e90614691565b60405180910390fd5b610c628383836126f8565b505050565b610c6f61252e565b73ffffffffffffffffffffffffffffffffffffffff16610c8d611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610ce3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cda906145f1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6b90614671565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610d98611b42565b836040518363ffffffff1660e01b8152600401610db69291906142a5565b602060405180830381600087803b158015610dd057600080fd5b505af1158015610de4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e089190613a5e565b505050565b6000610e6082600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061290f90919063ffffffff16565b905092915050565b610e7061252e565b73ffffffffffffffffffffffffffffffffffffffff16610e8e611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edb906145f1565b60405180910390fd5b6000610eee611b42565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610f36573d6000803e3d6000fd5b5050565b610f4261252e565b73ffffffffffffffffffffffffffffffffffffffff16610f60611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610fb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fad906145f1565b60405180910390fd5b80600f8190555050565b610fdb83838360405180602001604052806000815250611d8b565b505050565b600080610ff783600361292990919063ffffffff16565b50905080915050919050565b61100b61252e565b73ffffffffffffffffffffffffffffffffffffffff16611029611b42565b73ffffffffffffffffffffffffffffffffffffffff161461107f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611076906145f1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6110c5611b42565b836040518363ffffffff1660e01b81526004016110e39291906142a5565b602060405180830381600087803b1580156110fd57600080fd5b505af1158015611111573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111359190613a5e565b5050565b611142826112db565b73ffffffffffffffffffffffffffffffffffffffff1661116061252e565b73ffffffffffffffffffffffffffffffffffffffff16146111b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ad906143f1565b60405180910390fd5b600115156111c382610996565b151514611205576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111fc90614631565b60405180910390fd5b60076000838152602001908152602001600020604051611225919061419c565b604051809103902081805190602001201415611276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126d90614711565b60405180910390fd5b8060076000848152602001908152602001600020908051906020019061129d9291906136c6565b507f9b99933b2323816aeb124de92ee55fb03c4bae278986d8ddaa7c3e25c07a5f2d82826040516112cf92919061474c565b60405180910390a15050565b600061130b826040518060600160405280602981526020016153326029913960036129559092919063ffffffff16565b9050919050565b606060076000838152602001908152602001600020805461133290614a43565b80601f016020809104026020016040519081016040528092919081815260200182805461135e90614a43565b80156113ab5780601f10611380576101008083540402835291602001916113ab565b820191906000526020600020905b81548152906001019060200180831161138e57829003601f168201915b50505050509050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611428576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141f90614551565b60405180910390fd5b61146f600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612974565b9050919050565b61147e61252e565b73ffffffffffffffffffffffffffffffffffffffff1661149c611b42565b73ffffffffffffffffffffffffffffffffffffffff16146114f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e9906145f1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b681bc16d674ec800000081565b6115ce6115c861252e565b8361261a565b61160d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611604906146f1565b60405180910390fd5b6001151561161a82610996565b15151461165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165390614631565b60405180910390fd5b806007600084815260200190815260200160002090805190602001906116839291906136c6565b5061168d82612989565b817fa787526221baec058cfd67e998a880714d9bda0ec167ab800ac5974a92b2f6406116b761252e565b836040516116c6929190614275565b60405180910390a25050565b681bc16d674ec80000008214806116f15750683782dace9d9000000082145b806117045750686f05b59d3b2000000082145b611743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161173a90614511565b60405180910390fd5b60118310611786576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177d906143d1565b60405180910390fd5b6117a083611792611ded565b612a8f90919063ffffffff16565b600f5410156117e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117db90614571565b60405180910390fd5b67ffffffffffffffef811061182e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611825906145b1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306118818787612aa590919063ffffffff16565b6040518463ffffffff1660e01b815260040161189f939291906141f2565b602060405180830381600087803b1580156118b957600080fd5b505af11580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613a5e565b50600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68611969606461195b605061194d8989612aa590919063ffffffff16565b612aa590919063ffffffff16565b612abb90919063ffffffff16565b6040518263ffffffff1660e01b81526004016119859190614731565b602060405180830381600087803b15801561199f57600080fd5b505af11580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d79190613a5e565b5060006119e2611ded565b905060005b84811015611adf5760001515600960008386611a039190614866565b815260200190815260200160002060009054906101000a900460ff16151514611a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5890614411565b60405180910390fd5b611a7233611a6d611ded565b612ad1565b6001600960008386611a849190614866565b815260200190815260200160002060006101000a81548160ff0219169083151502179055508083611ab59190614866565b60086000848152602001908152602001600020819055508080611ad790614aa6565b9150506119e7565b507f9db9332332291706d6e33656780a4af5f3e1f9a83a3ea7b2d5bb8a5d02fae9a13382868686604051611b17959493929190614321565b60405180910390a150505050565b600060086000838152602001908152602001600020549050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600c8054611b7a90614a43565b80601f0160208091040260200160405190810160405280929190818152602001828054611ba690614a43565b8015611bf35780601f10611bc857610100808354040283529160200191611bf3565b820191906000526020600020905b815481529060010190602001808311611bd657829003601f168201915b5050505050905090565b611c0561252e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6a906144b1565b60405180910390fd5b80600a6000611c8061252e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611d2d61252e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611d729190614374565b60405180910390a35050565b686f05b59d3b2000000081565b611d9c611d9661252e565b8361261a565b611ddb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd290614691565b60405180910390fd5b611de784848484612aef565b50505050565b6000611df960036125ef565b905090565b600015156009600083815260200190815260200160002060009054906101000a900460ff16151514611e65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5c906146d1565b60405180910390fd5b681bc16d674ec8000000821480611e845750683782dace9d9000000082145b80611e975750686f05b59d3b2000000082145b611ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ecd90614511565b60405180910390fd5b611ef16001611ee3611ded565b612a8f90919063ffffffff16565b600f541015611f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f2c90614571565b60405180910390fd5b67ffffffffffffffef8110611f7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f76906145b1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401611fde939291906141f2565b602060405180830381600087803b158015611ff857600080fd5b505af115801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190613a5e565b50600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c686120966064612088605087612aa590919063ffffffff16565b612abb90919063ffffffff16565b6040518263ffffffff1660e01b81526004016120b29190614731565b602060405180830381600087803b1580156120cc57600080fd5b505af11580156120e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121049190613a5e565b50600061210f611ded565b905061211b3382612ad1565b60016009600084815260200190815260200160002060006101000a81548160ff0219169083151502179055508160086000838152602001908152602001600020819055507f9db9332332291706d6e33656780a4af5f3e1f9a83a3ea7b2d5bb8a5d02fae9a13382600186866040516121979594939291906142ce565b60405180910390a1505050565b60606121af82612511565b6121b857600080fd5b6121c06121fd565b6121c983612b4b565b6040516020016121da9291906141b3565b6040516020818303038152906040529050919050565b683782dace9d9000000081565b60606040518060400160405280602081526020017f68747470733a2f2f6170702e616934332e6172742f6170692f737472696e672f815250905090565b60008015156009600084815260200190815260200160002060009054906101000a900460ff161515149050919050565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61230661252e565b73ffffffffffffffffffffffffffffffffffffffff16612324611b42565b73ffffffffffffffffffffffffffffffffffffffff161461237a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612371906145f1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156123ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123e190614451565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000612527826003612cf890919063ffffffff16565b9050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166125a9836112db565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006125fd82600001612d12565b9050919050565b600081836126129190614947565b905092915050565b600061262582612511565b612664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265b906144f1565b60405180910390fd5b600061266f836112db565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806126de57508373ffffffffffffffffffffffffffffffffffffffff166126c6846107f9565b73ffffffffffffffffffffffffffffffffffffffff16145b806126ef57506126ee818561226a565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612718826112db565b73ffffffffffffffffffffffffffffffffffffffff161461276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614611565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156127de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d590614491565b60405180910390fd5b6127e9838383612d27565b6127f4600082612536565b61284581600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d2c90919063ffffffff16565b5061289781600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d4690919063ffffffff16565b506128ae81836003612d609092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061291e8360000183612d95565b60001c905092915050565b60008060008061293c8660000186612e2f565b915091508160001c8160001c9350935050509250929050565b6000612968846000018460001b84612e6f565b60001c90509392505050565b600061298282600001612ef0565b9050919050565b6000612994826112db565b90506129a281600084612d27565b6129ad600083612536565b6129fe82600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d2c90919063ffffffff16565b50612a168260006003612d609092919063ffffffff16565b50600e6000815480929190612a2a90614aa6565b919050555081600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60008183612a9d9190614866565b905092915050565b60008183612ab391906148ed565b905092915050565b60008183612ac991906148bc565b905092915050565b612aeb828260405180602001604052806000815250612f01565b5050565b612afa8484846126f8565b612b0684848484612f5c565b612b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3c90614431565b60405180910390fd5b50505050565b60606000821415612b93576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612cf3565b600082905060005b60008214612bc5578080612bae90614aa6565b915050600a82612bbe91906148bc565b9150612b9b565b60008167ffffffffffffffff811115612c07577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612c395781602001600182028036833780820191505090505b5090505b60008514612cec57600182612c529190614947565b9150600a85612c619190614aef565b6030612c6d9190614866565b60f81b818381518110612ca9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612ce591906148bc565b9450612c3d565b8093505050505b919050565b6000612d0a836000018360001b6130c0565b905092915050565b6000612d20826000016130e0565b9050919050565b505050565b6000612d3e836000018360001b6130f5565b905092915050565b6000612d58836000018360001b61327f565b905092915050565b6000612d8c846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b6132ef565b90509392505050565b600081836000018054905011612de0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dd7906143b1565b60405180910390fd5b826000018281548110612e1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b6000806000612e4a848660000161332a90919063ffffffff16565b9050808560020160008381526020019081526020016000205492509250509250929050565b6000808460020160008581526020019081526020016000205490506000801b81141580612ea25750612ea185856130c0565b5b8390612ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612edb919061438f565b60405180910390fd5b50809150509392505050565b600081600001805490509050919050565b612f0b8383613341565b612f186000848484612f5c565b612f57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f4e90614431565b60405180910390fd5b505050565b6000612f7d8473ffffffffffffffffffffffffffffffffffffffff166134cf565b612f8a57600190506130b8565b600061305163150b7a0260e01b612f9f61252e565b888787604051602401612fb59493929190614229565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001615300603291398773ffffffffffffffffffffffffffffffffffffffff166134e29092919063ffffffff16565b90506000818060200190518101906130699190613ab0565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b60006130d882846000016134fa90919063ffffffff16565b905092915050565b60006130ee82600001612ef0565b9050919050565b600080836001016000848152602001908152602001600020549050600081146132735760006001826131279190614947565b905060006001866000018054905061313f9190614947565b9050600086600001828154811061317f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106131c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055506001836131e49190614866565b8760010160008381526020019081526020016000208190555086600001805480613237577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050613279565b60009150505b92915050565b600061328b8383613511565b6132e45782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506132e9565b600090505b92915050565b60008184600201600085815260200190815260200160002081905550613321838560000161353490919063ffffffff16565b90509392505050565b60006133398360000183612d95565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133a890614591565b60405180910390fd5b6133ba81612511565b156133fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133f190614471565b60405180910390fd5b61340660008383612d27565b61345781600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d4690919063ffffffff16565b5061346e81836003612d609092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b60606134f1848460008561354b565b90509392505050565b60006135098360000183613511565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b6000613543836000018361327f565b905092915050565b606082471015613590576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613587906144d1565b60405180910390fd5b613599856134cf565b6135d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135cf906146b1565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516136019190614185565b60006040518083038185875af1925050503d806000811461363e576040519150601f19603f3d011682016040523d82523d6000602084013e613643565b606091505b509150915061365382828661365f565b92505050949350505050565b6060831561366f578290506136bf565b6000835111156136825782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136b6919061438f565b60405180910390fd5b9392505050565b8280546136d290614a43565b90600052602060002090601f0160209004810192826136f4576000855561373b565b82601f1061370d57805160ff191683800117855561373b565b8280016001018555821561373b579182015b8281111561373a57825182559160200191906001019061371f565b5b509050613748919061374c565b5090565b5b8082111561376557600081600090555060010161374d565b5090565b600061377c613777846147a1565b61477c565b90508281526020810184848401111561379457600080fd5b61379f848285614a01565b509392505050565b60006137ba6137b5846147d2565b61477c565b9050828152602081018484840111156137d257600080fd5b6137dd848285614a01565b509392505050565b6000813590506137f4816152a3565b92915050565b600081359050613809816152ba565b92915050565b60008151905061381e816152ba565b92915050565b600081359050613833816152d1565b92915050565b600081519050613848816152d1565b92915050565b600082601f83011261385f57600080fd5b813561386f848260208601613769565b91505092915050565b600082601f83011261388957600080fd5b81356138998482602086016137a7565b91505092915050565b6000813590506138b1816152e8565b92915050565b6000602082840312156138c957600080fd5b60006138d7848285016137e5565b91505092915050565b600080604083850312156138f357600080fd5b6000613901858286016137e5565b9250506020613912858286016137e5565b9150509250929050565b60008060006060848603121561393157600080fd5b600061393f868287016137e5565b9350506020613950868287016137e5565b9250506040613961868287016138a2565b9150509250925092565b6000806000806080858703121561398157600080fd5b600061398f878288016137e5565b94505060206139a0878288016137e5565b93505060406139b1878288016138a2565b925050606085013567ffffffffffffffff8111156139ce57600080fd5b6139da8782880161384e565b91505092959194509250565b600080604083850312156139f957600080fd5b6000613a07858286016137e5565b9250506020613a18858286016137fa565b9150509250929050565b60008060408385031215613a3557600080fd5b6000613a43858286016137e5565b9250506020613a54858286016138a2565b9150509250929050565b600060208284031215613a7057600080fd5b6000613a7e8482850161380f565b91505092915050565b600060208284031215613a9957600080fd5b6000613aa784828501613824565b91505092915050565b600060208284031215613ac257600080fd5b6000613ad084828501613839565b91505092915050565b600060208284031215613aeb57600080fd5b600082013567ffffffffffffffff811115613b0557600080fd5b613b1184828501613878565b91505092915050565b600060208284031215613b2c57600080fd5b6000613b3a848285016138a2565b91505092915050565b60008060408385031215613b5657600080fd5b6000613b64858286016138a2565b925050602083013567ffffffffffffffff811115613b8157600080fd5b613b8d85828601613878565b9150509250929050565b60008060408385031215613baa57600080fd5b6000613bb8858286016138a2565b9250506020613bc9858286016138a2565b9150509250929050565b600080600060608486031215613be857600080fd5b6000613bf6868287016138a2565b9350506020613c07868287016138a2565b9250506040613c18868287016138a2565b9150509250925092565b613c2b8161497b565b82525050565b613c3a8161498d565b82525050565b6000613c4b82614818565b613c55818561482e565b9350613c65818560208601614a10565b613c6e81614bdc565b840191505092915050565b6000613c8482614818565b613c8e818561483f565b9350613c9e818560208601614a10565b80840191505092915050565b60008154613cb781614a43565b613cc1818661483f565b94506001821660008114613cdc5760018114613ced57613d20565b60ff19831686528186019350613d20565b613cf685614803565b60005b83811015613d1857815481890152600182019150602081019050613cf9565b838801955050505b50505092915050565b613d32816149ef565b82525050565b6000613d4382614823565b613d4d818561484a565b9350613d5d818560208601614a10565b613d6681614bdc565b840191505092915050565b6000613d7c82614823565b613d86818561485b565b9350613d96818560208601614a10565b80840191505092915050565b6000613daf60228361484a565b9150613dba82614bed565b604082019050919050565b6000613dd2601d8361484a565b9150613ddd82614c3c565b602082019050919050565b6000613df5601f8361484a565b9150613e0082614c65565b602082019050919050565b6000613e1860248361484a565b9150613e2382614c8e565b604082019050919050565b6000613e3b60328361484a565b9150613e4682614cdd565b604082019050919050565b6000613e5e60268361484a565b9150613e6982614d2c565b604082019050919050565b6000613e81601c8361484a565b9150613e8c82614d7b565b602082019050919050565b6000613ea460248361484a565b9150613eaf82614da4565b604082019050919050565b6000613ec760198361484a565b9150613ed282614df3565b602082019050919050565b6000613eea60268361484a565b9150613ef582614e1c565b604082019050919050565b6000613f0d602c8361484a565b9150613f1882614e6b565b604082019050919050565b6000613f3060168361484a565b9150613f3b82614eba565b602082019050919050565b6000613f5360388361484a565b9150613f5e82614ee3565b604082019050919050565b6000613f76602a8361484a565b9150613f8182614f32565b604082019050919050565b6000613f9960178361484a565b9150613fa482614f81565b602082019050919050565b6000613fbc60208361484a565b9150613fc782614faa565b602082019050919050565b6000613fdf60108361484a565b9150613fea82614fd3565b602082019050919050565b6000614002602c8361484a565b915061400d82614ffc565b604082019050919050565b600061402560208361484a565b91506140308261504b565b602082019050919050565b600061404860298361484a565b915061405382615074565b604082019050919050565b600061406b60218361484a565b9150614076826150c3565b604082019050919050565b600061408e60218361484a565b915061409982615112565b604082019050919050565b60006140b160208361484a565b91506140bc82615161565b602082019050919050565b60006140d460318361484a565b91506140df8261518a565b604082019050919050565b60006140f7601d8361484a565b9150614102826151d9565b602082019050919050565b600061411a60108361484a565b915061412582615202565b602082019050919050565b600061413d60308361484a565b91506141488261522b565b604082019050919050565b600061416060178361484a565b915061416b8261527a565b602082019050919050565b61417f816149e5565b82525050565b60006141918284613c79565b915081905092915050565b60006141a88284613caa565b915081905092915050565b60006141bf8285613d71565b91506141cb8284613d71565b91508190509392505050565b60006020820190506141ec6000830184613c22565b92915050565b60006060820190506142076000830186613c22565b6142146020830185613c22565b6142216040830184614176565b949350505050565b600060808201905061423e6000830187613c22565b61424b6020830186613c22565b6142586040830185614176565b818103606083015261426a8184613c40565b905095945050505050565b600060408201905061428a6000830185613c22565b818103602083015261429c8184613d38565b90509392505050565b60006040820190506142ba6000830185613c22565b6142c76020830184614176565b9392505050565b600060a0820190506142e36000830188613c22565b6142f06020830187614176565b6142fd6040830186613d29565b61430a6060830185614176565b6143176080830184614176565b9695505050505050565b600060a0820190506143366000830188613c22565b6143436020830187614176565b6143506040830186614176565b61435d6060830185614176565b61436a6080830184614176565b9695505050505050565b60006020820190506143896000830184613c31565b92915050565b600060208201905081810360008301526143a98184613d38565b905092915050565b600060208201905081810360008301526143ca81613da2565b9050919050565b600060208201905081810360008301526143ea81613dc5565b9050919050565b6000602082019050818103600083015261440a81613de8565b9050919050565b6000602082019050818103600083015261442a81613e0b565b9050919050565b6000602082019050818103600083015261444a81613e2e565b9050919050565b6000602082019050818103600083015261446a81613e51565b9050919050565b6000602082019050818103600083015261448a81613e74565b9050919050565b600060208201905081810360008301526144aa81613e97565b9050919050565b600060208201905081810360008301526144ca81613eba565b9050919050565b600060208201905081810360008301526144ea81613edd565b9050919050565b6000602082019050818103600083015261450a81613f00565b9050919050565b6000602082019050818103600083015261452a81613f23565b9050919050565b6000602082019050818103600083015261454a81613f46565b9050919050565b6000602082019050818103600083015261456a81613f69565b9050919050565b6000602082019050818103600083015261458a81613f8c565b9050919050565b600060208201905081810360008301526145aa81613faf565b9050919050565b600060208201905081810360008301526145ca81613fd2565b9050919050565b600060208201905081810360008301526145ea81613ff5565b9050919050565b6000602082019050818103600083015261460a81614018565b9050919050565b6000602082019050818103600083015261462a8161403b565b9050919050565b6000602082019050818103600083015261464a8161405e565b9050919050565b6000602082019050818103600083015261466a81614081565b9050919050565b6000602082019050818103600083015261468a816140a4565b9050919050565b600060208201905081810360008301526146aa816140c7565b9050919050565b600060208201905081810360008301526146ca816140ea565b9050919050565b600060208201905081810360008301526146ea8161410d565b9050919050565b6000602082019050818103600083015261470a81614130565b9050919050565b6000602082019050818103600083015261472a81614153565b9050919050565b60006020820190506147466000830184614176565b92915050565b60006040820190506147616000830185614176565b81810360208301526147738184613d38565b90509392505050565b6000614786614797565b90506147928282614a75565b919050565b6000604051905090565b600067ffffffffffffffff8211156147bc576147bb614bad565b5b6147c582614bdc565b9050602081019050919050565b600067ffffffffffffffff8211156147ed576147ec614bad565b5b6147f682614bdc565b9050602081019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000614871826149e5565b915061487c836149e5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148b1576148b0614b20565b5b828201905092915050565b60006148c7826149e5565b91506148d2836149e5565b9250826148e2576148e1614b4f565b5b828204905092915050565b60006148f8826149e5565b9150614903836149e5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561493c5761493b614b20565b5b828202905092915050565b6000614952826149e5565b915061495d836149e5565b9250828210156149705761496f614b20565b5b828203905092915050565b6000614986826149c5565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006149fa826149e5565b9050919050565b82818337600083830152505050565b60005b83811015614a2e578082015181840152602081019050614a13565b83811115614a3d576000848401525b50505050565b60006002820490506001821680614a5b57607f821691505b60208210811415614a6f57614a6e614b7e565b5b50919050565b614a7e82614bdc565b810181811067ffffffffffffffff82111715614a9d57614a9c614bad565b5b80604052505050565b6000614ab1826149e5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614ae457614ae3614b20565b5b600182019050919050565b6000614afa826149e5565b9150614b05836149e5565b925082614b1557614b14614b4f565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b7f6d6178696d756d206f6620313620537472696e6773206174206f6e6365000000600082015250565b7f4552433732313a2063616c6c6572206973206e6f7420746865206f776e657200600082015250565b7f7365656420616c726561647920757365642c2075736520616e6f74686572207360008201527f7461727400000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f64757374416d6f756e74206e6f7420636f727265637400000000000000000000600082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4e6f7420656e6f75676820537472696e6773206c656674000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f73656564206d6178203820627974657300000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552524f523a206e616d6520646f6573206e6f7420666f6c6c6f772072756c6560008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552524f523a2063616e6e6f742072656d6f7665206475737420746f6b656e73600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f73656564207573656420616c7265647900000000000000000000000000000000600082015250565b7f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656400000000000000000000000000000000602082015250565b7f4552524f523a206e616d65206973207468652073616d65000000000000000000600082015250565b6152ac8161497b565b81146152b757600080fd5b50565b6152c38161498d565b81146152ce57600080fd5b50565b6152da81614999565b81146152e557600080fd5b50565b6152f1816149e5565b81146152fc57600080fd5b5056fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220c47a8998073a2bfa4162b558b65eebfd121b2643d8d1bb89957aac8a54e7d60b64736f6c63430008010033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000424242115b5bbdc12a1f5c06dd8dd0ddd03c321d000000000000000000000000000000000000000000000000000000000000000c4149343320537472696e677300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006535452494e470000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061021c5760003560e01c8063715018a611610125578063b88d4fde116100ad578063cb67e96d1161007c578063cb67e96d14610637578063d547cfb714610655578063e8d01cf014610673578063e985e9c5146106a3578063f2fde38b146106d35761021c565b8063b88d4fde146105b1578063c1bd8cf9146105cd578063c275683d146105eb578063c87b56dd146106075761021c565b80638b456d0b116100f45780638b456d0b1461050b5780638da5cb5b1461053b57806395d89b4114610559578063a22cb46514610577578063b87cc30f146105935761021c565b8063715018a6146104ab57806374dec154146104b55780637641e6f3146104d35780637aad0446146104ef5761021c565b80633ccfd60b116101a85780635cdd776f116101775780635cdd776f146103e357806362e21487146103ff5780636352211e1461041b5780636d5224181461044b57806370a082311461047b5761021c565b80633ccfd60b14610371578063404c7cdd1461037b57806342842e0e146103975780634f6ccce7146103b35761021c565b80631400d1e4116101ef5780631400d1e4146102bb57806318160ddd146102eb57806323b872dd146103095780632c58bb88146103255780632f745c59146103415761021c565b806301ffc9a71461022157806306fdde0314610251578063081812fc1461026f578063095ea7b31461029f575b600080fd5b61023b60048036038101906102369190613a87565b6106ef565b6040516102489190614374565b60405180910390f35b610259610767565b604051610266919061438f565b60405180910390f35b61028960048036038101906102849190613b1a565b6107f9565b60405161029691906141d7565b60405180910390f35b6102b960048036038101906102b49190613a22565b61087e565b005b6102d560048036038101906102d09190613ad9565b610996565b6040516102e29190614374565b60405180910390f35b6102f3610be2565b6040516103009190614731565b60405180910390f35b610323600480360381019061031e919061391c565b610c07565b005b61033f600480360381019061033a9190613a22565b610c67565b005b61035b60048036038101906103569190613a22565b610e0d565b6040516103689190614731565b60405180910390f35b610379610e68565b005b61039560048036038101906103909190613b1a565b610f3a565b005b6103b160048036038101906103ac919061391c565b610fc0565b005b6103cd60048036038101906103c89190613b1a565b610fe0565b6040516103da9190614731565b60405180910390f35b6103fd60048036038101906103f89190613b1a565b611003565b005b61041960048036038101906104149190613b43565b611139565b005b61043560048036038101906104309190613b1a565b6112db565b60405161044291906141d7565b60405180910390f35b61046560048036038101906104609190613b1a565b611312565b604051610472919061438f565b60405180910390f35b610495600480360381019061049091906138b7565b6113b7565b6040516104a29190614731565b60405180910390f35b6104b3611476565b005b6104bd6115b0565b6040516104ca9190614731565b60405180910390f35b6104ed60048036038101906104e89190613b43565b6115bd565b005b61050960048036038101906105049190613bd3565b6116d2565b005b61052560048036038101906105209190613b1a565b611b25565b6040516105329190614731565b60405180910390f35b610543611b42565b60405161055091906141d7565b60405180910390f35b610561611b6b565b60405161056e919061438f565b60405180910390f35b610591600480360381019061058c91906139e6565b611bfd565b005b61059b611d7e565b6040516105a89190614731565b60405180910390f35b6105cb60048036038101906105c6919061396b565b611d8b565b005b6105d5611ded565b6040516105e29190614731565b60405180910390f35b61060560048036038101906106009190613b97565b611dfe565b005b610621600480360381019061061c9190613b1a565b6121a4565b60405161062e919061438f565b60405180910390f35b61063f6121f0565b60405161064c9190614731565b60405180910390f35b61065d6121fd565b60405161066a919061438f565b60405180910390f35b61068d60048036038101906106889190613b1a565b61223a565b60405161069a9190614374565b60405180910390f35b6106bd60048036038101906106b891906138e0565b61226a565b6040516106ca9190614374565b60405180910390f35b6106ed60048036038101906106e891906138b7565b6122fe565b005b60006106fa826124a7565b80610760575060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff165b9050919050565b6060600b805461077690614a43565b80601f01602080910402602001604051908101604052809291908181526020018280546107a290614a43565b80156107ef5780601f106107c4576101008083540402835291602001916107ef565b820191906000526020600020905b8154815290600101906020018083116107d257829003601f168201915b5050505050905090565b600061080482612511565b610843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083a906145d1565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610889826112db565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156108fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f190614651565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661091961252e565b73ffffffffffffffffffffffffffffffffffffffff16148061094857506109478161094261252e565b61226a565b5b610987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097e90614531565b60405180910390fd5b6109918383612536565b505050565b6000808290506000815114156109b0576000915050610bdd565b6018815111156109c4576000915050610bdd565b602060f81b81600081518110610a03577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a40576000915050610bdd565b602060f81b8160018351610a549190614947565b81518110610a8b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610ac8576000915050610bdd565b60005b8151811015610bd657607e60f81b828281518110610b12577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161180610bb35750602060f81b828281518110610b84577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916105b15610bc357600092505050610bdd565b8080610bce90614aa6565b915050610acb565b5060019150505b919050565b6000610c02600e54610bf460036125ef565b61260490919063ffffffff16565b905090565b610c18610c1261252e565b8261261a565b610c57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4e90614691565b60405180910390fd5b610c628383836126f8565b505050565b610c6f61252e565b73ffffffffffffffffffffffffffffffffffffffff16610c8d611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610ce3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cda906145f1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6b90614671565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610d98611b42565b836040518363ffffffff1660e01b8152600401610db69291906142a5565b602060405180830381600087803b158015610dd057600080fd5b505af1158015610de4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e089190613a5e565b505050565b6000610e6082600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061290f90919063ffffffff16565b905092915050565b610e7061252e565b73ffffffffffffffffffffffffffffffffffffffff16610e8e611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edb906145f1565b60405180910390fd5b6000610eee611b42565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610f36573d6000803e3d6000fd5b5050565b610f4261252e565b73ffffffffffffffffffffffffffffffffffffffff16610f60611b42565b73ffffffffffffffffffffffffffffffffffffffff1614610fb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fad906145f1565b60405180910390fd5b80600f8190555050565b610fdb83838360405180602001604052806000815250611d8b565b505050565b600080610ff783600361292990919063ffffffff16565b50905080915050919050565b61100b61252e565b73ffffffffffffffffffffffffffffffffffffffff16611029611b42565b73ffffffffffffffffffffffffffffffffffffffff161461107f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611076906145f1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6110c5611b42565b836040518363ffffffff1660e01b81526004016110e39291906142a5565b602060405180830381600087803b1580156110fd57600080fd5b505af1158015611111573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111359190613a5e565b5050565b611142826112db565b73ffffffffffffffffffffffffffffffffffffffff1661116061252e565b73ffffffffffffffffffffffffffffffffffffffff16146111b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ad906143f1565b60405180910390fd5b600115156111c382610996565b151514611205576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111fc90614631565b60405180910390fd5b60076000838152602001908152602001600020604051611225919061419c565b604051809103902081805190602001201415611276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126d90614711565b60405180910390fd5b8060076000848152602001908152602001600020908051906020019061129d9291906136c6565b507f9b99933b2323816aeb124de92ee55fb03c4bae278986d8ddaa7c3e25c07a5f2d82826040516112cf92919061474c565b60405180910390a15050565b600061130b826040518060600160405280602981526020016153326029913960036129559092919063ffffffff16565b9050919050565b606060076000838152602001908152602001600020805461133290614a43565b80601f016020809104026020016040519081016040528092919081815260200182805461135e90614a43565b80156113ab5780601f10611380576101008083540402835291602001916113ab565b820191906000526020600020905b81548152906001019060200180831161138e57829003601f168201915b50505050509050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611428576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141f90614551565b60405180910390fd5b61146f600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612974565b9050919050565b61147e61252e565b73ffffffffffffffffffffffffffffffffffffffff1661149c611b42565b73ffffffffffffffffffffffffffffffffffffffff16146114f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e9906145f1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b681bc16d674ec800000081565b6115ce6115c861252e565b8361261a565b61160d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611604906146f1565b60405180910390fd5b6001151561161a82610996565b15151461165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165390614631565b60405180910390fd5b806007600084815260200190815260200160002090805190602001906116839291906136c6565b5061168d82612989565b817fa787526221baec058cfd67e998a880714d9bda0ec167ab800ac5974a92b2f6406116b761252e565b836040516116c6929190614275565b60405180910390a25050565b681bc16d674ec80000008214806116f15750683782dace9d9000000082145b806117045750686f05b59d3b2000000082145b611743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161173a90614511565b60405180910390fd5b60118310611786576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177d906143d1565b60405180910390fd5b6117a083611792611ded565b612a8f90919063ffffffff16565b600f5410156117e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117db90614571565b60405180910390fd5b67ffffffffffffffef811061182e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611825906145b1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306118818787612aa590919063ffffffff16565b6040518463ffffffff1660e01b815260040161189f939291906141f2565b602060405180830381600087803b1580156118b957600080fd5b505af11580156118cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f19190613a5e565b50600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68611969606461195b605061194d8989612aa590919063ffffffff16565b612aa590919063ffffffff16565b612abb90919063ffffffff16565b6040518263ffffffff1660e01b81526004016119859190614731565b602060405180830381600087803b15801561199f57600080fd5b505af11580156119b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d79190613a5e565b5060006119e2611ded565b905060005b84811015611adf5760001515600960008386611a039190614866565b815260200190815260200160002060009054906101000a900460ff16151514611a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5890614411565b60405180910390fd5b611a7233611a6d611ded565b612ad1565b6001600960008386611a849190614866565b815260200190815260200160002060006101000a81548160ff0219169083151502179055508083611ab59190614866565b60086000848152602001908152602001600020819055508080611ad790614aa6565b9150506119e7565b507f9db9332332291706d6e33656780a4af5f3e1f9a83a3ea7b2d5bb8a5d02fae9a13382868686604051611b17959493929190614321565b60405180910390a150505050565b600060086000838152602001908152602001600020549050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600c8054611b7a90614a43565b80601f0160208091040260200160405190810160405280929190818152602001828054611ba690614a43565b8015611bf35780601f10611bc857610100808354040283529160200191611bf3565b820191906000526020600020905b815481529060010190602001808311611bd657829003601f168201915b5050505050905090565b611c0561252e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6a906144b1565b60405180910390fd5b80600a6000611c8061252e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611d2d61252e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611d729190614374565b60405180910390a35050565b686f05b59d3b2000000081565b611d9c611d9661252e565b8361261a565b611ddb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd290614691565b60405180910390fd5b611de784848484612aef565b50505050565b6000611df960036125ef565b905090565b600015156009600083815260200190815260200160002060009054906101000a900460ff16151514611e65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5c906146d1565b60405180910390fd5b681bc16d674ec8000000821480611e845750683782dace9d9000000082145b80611e975750686f05b59d3b2000000082145b611ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ecd90614511565b60405180910390fd5b611ef16001611ee3611ded565b612a8f90919063ffffffff16565b600f541015611f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f2c90614571565b60405180910390fd5b67ffffffffffffffef8110611f7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f76906145b1565b60405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401611fde939291906141f2565b602060405180830381600087803b158015611ff857600080fd5b505af115801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190613a5e565b50600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c686120966064612088605087612aa590919063ffffffff16565b612abb90919063ffffffff16565b6040518263ffffffff1660e01b81526004016120b29190614731565b602060405180830381600087803b1580156120cc57600080fd5b505af11580156120e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121049190613a5e565b50600061210f611ded565b905061211b3382612ad1565b60016009600084815260200190815260200160002060006101000a81548160ff0219169083151502179055508160086000838152602001908152602001600020819055507f9db9332332291706d6e33656780a4af5f3e1f9a83a3ea7b2d5bb8a5d02fae9a13382600186866040516121979594939291906142ce565b60405180910390a1505050565b60606121af82612511565b6121b857600080fd5b6121c06121fd565b6121c983612b4b565b6040516020016121da9291906141b3565b6040516020818303038152906040529050919050565b683782dace9d9000000081565b60606040518060400160405280602081526020017f68747470733a2f2f6170702e616934332e6172742f6170692f737472696e672f815250905090565b60008015156009600084815260200190815260200160002060009054906101000a900460ff161515149050919050565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61230661252e565b73ffffffffffffffffffffffffffffffffffffffff16612324611b42565b73ffffffffffffffffffffffffffffffffffffffff161461237a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612371906145f1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156123ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123e190614451565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000612527826003612cf890919063ffffffff16565b9050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166125a9836112db565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006125fd82600001612d12565b9050919050565b600081836126129190614947565b905092915050565b600061262582612511565b612664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265b906144f1565b60405180910390fd5b600061266f836112db565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806126de57508373ffffffffffffffffffffffffffffffffffffffff166126c6846107f9565b73ffffffffffffffffffffffffffffffffffffffff16145b806126ef57506126ee818561226a565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612718826112db565b73ffffffffffffffffffffffffffffffffffffffff161461276e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276590614611565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156127de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d590614491565b60405180910390fd5b6127e9838383612d27565b6127f4600082612536565b61284581600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d2c90919063ffffffff16565b5061289781600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d4690919063ffffffff16565b506128ae81836003612d609092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061291e8360000183612d95565b60001c905092915050565b60008060008061293c8660000186612e2f565b915091508160001c8160001c9350935050509250929050565b6000612968846000018460001b84612e6f565b60001c90509392505050565b600061298282600001612ef0565b9050919050565b6000612994826112db565b90506129a281600084612d27565b6129ad600083612536565b6129fe82600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d2c90919063ffffffff16565b50612a168260006003612d609092919063ffffffff16565b50600e6000815480929190612a2a90614aa6565b919050555081600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60008183612a9d9190614866565b905092915050565b60008183612ab391906148ed565b905092915050565b60008183612ac991906148bc565b905092915050565b612aeb828260405180602001604052806000815250612f01565b5050565b612afa8484846126f8565b612b0684848484612f5c565b612b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3c90614431565b60405180910390fd5b50505050565b60606000821415612b93576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612cf3565b600082905060005b60008214612bc5578080612bae90614aa6565b915050600a82612bbe91906148bc565b9150612b9b565b60008167ffffffffffffffff811115612c07577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612c395781602001600182028036833780820191505090505b5090505b60008514612cec57600182612c529190614947565b9150600a85612c619190614aef565b6030612c6d9190614866565b60f81b818381518110612ca9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612ce591906148bc565b9450612c3d565b8093505050505b919050565b6000612d0a836000018360001b6130c0565b905092915050565b6000612d20826000016130e0565b9050919050565b505050565b6000612d3e836000018360001b6130f5565b905092915050565b6000612d58836000018360001b61327f565b905092915050565b6000612d8c846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b6132ef565b90509392505050565b600081836000018054905011612de0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dd7906143b1565b60405180910390fd5b826000018281548110612e1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b6000806000612e4a848660000161332a90919063ffffffff16565b9050808560020160008381526020019081526020016000205492509250509250929050565b6000808460020160008581526020019081526020016000205490506000801b81141580612ea25750612ea185856130c0565b5b8390612ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612edb919061438f565b60405180910390fd5b50809150509392505050565b600081600001805490509050919050565b612f0b8383613341565b612f186000848484612f5c565b612f57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f4e90614431565b60405180910390fd5b505050565b6000612f7d8473ffffffffffffffffffffffffffffffffffffffff166134cf565b612f8a57600190506130b8565b600061305163150b7a0260e01b612f9f61252e565b888787604051602401612fb59493929190614229565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001615300603291398773ffffffffffffffffffffffffffffffffffffffff166134e29092919063ffffffff16565b90506000818060200190518101906130699190613ab0565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b60006130d882846000016134fa90919063ffffffff16565b905092915050565b60006130ee82600001612ef0565b9050919050565b600080836001016000848152602001908152602001600020549050600081146132735760006001826131279190614947565b905060006001866000018054905061313f9190614947565b9050600086600001828154811061317f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106131c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055506001836131e49190614866565b8760010160008381526020019081526020016000208190555086600001805480613237577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050613279565b60009150505b92915050565b600061328b8383613511565b6132e45782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506132e9565b600090505b92915050565b60008184600201600085815260200190815260200160002081905550613321838560000161353490919063ffffffff16565b90509392505050565b60006133398360000183612d95565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133a890614591565b60405180910390fd5b6133ba81612511565b156133fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133f190614471565b60405180910390fd5b61340660008383612d27565b61345781600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d4690919063ffffffff16565b5061346e81836003612d609092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b60606134f1848460008561354b565b90509392505050565b60006135098360000183613511565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b6000613543836000018361327f565b905092915050565b606082471015613590576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613587906144d1565b60405180910390fd5b613599856134cf565b6135d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135cf906146b1565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516136019190614185565b60006040518083038185875af1925050503d806000811461363e576040519150601f19603f3d011682016040523d82523d6000602084013e613643565b606091505b509150915061365382828661365f565b92505050949350505050565b6060831561366f578290506136bf565b6000835111156136825782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136b6919061438f565b60405180910390fd5b9392505050565b8280546136d290614a43565b90600052602060002090601f0160209004810192826136f4576000855561373b565b82601f1061370d57805160ff191683800117855561373b565b8280016001018555821561373b579182015b8281111561373a57825182559160200191906001019061371f565b5b509050613748919061374c565b5090565b5b8082111561376557600081600090555060010161374d565b5090565b600061377c613777846147a1565b61477c565b90508281526020810184848401111561379457600080fd5b61379f848285614a01565b509392505050565b60006137ba6137b5846147d2565b61477c565b9050828152602081018484840111156137d257600080fd5b6137dd848285614a01565b509392505050565b6000813590506137f4816152a3565b92915050565b600081359050613809816152ba565b92915050565b60008151905061381e816152ba565b92915050565b600081359050613833816152d1565b92915050565b600081519050613848816152d1565b92915050565b600082601f83011261385f57600080fd5b813561386f848260208601613769565b91505092915050565b600082601f83011261388957600080fd5b81356138998482602086016137a7565b91505092915050565b6000813590506138b1816152e8565b92915050565b6000602082840312156138c957600080fd5b60006138d7848285016137e5565b91505092915050565b600080604083850312156138f357600080fd5b6000613901858286016137e5565b9250506020613912858286016137e5565b9150509250929050565b60008060006060848603121561393157600080fd5b600061393f868287016137e5565b9350506020613950868287016137e5565b9250506040613961868287016138a2565b9150509250925092565b6000806000806080858703121561398157600080fd5b600061398f878288016137e5565b94505060206139a0878288016137e5565b93505060406139b1878288016138a2565b925050606085013567ffffffffffffffff8111156139ce57600080fd5b6139da8782880161384e565b91505092959194509250565b600080604083850312156139f957600080fd5b6000613a07858286016137e5565b9250506020613a18858286016137fa565b9150509250929050565b60008060408385031215613a3557600080fd5b6000613a43858286016137e5565b9250506020613a54858286016138a2565b9150509250929050565b600060208284031215613a7057600080fd5b6000613a7e8482850161380f565b91505092915050565b600060208284031215613a9957600080fd5b6000613aa784828501613824565b91505092915050565b600060208284031215613ac257600080fd5b6000613ad084828501613839565b91505092915050565b600060208284031215613aeb57600080fd5b600082013567ffffffffffffffff811115613b0557600080fd5b613b1184828501613878565b91505092915050565b600060208284031215613b2c57600080fd5b6000613b3a848285016138a2565b91505092915050565b60008060408385031215613b5657600080fd5b6000613b64858286016138a2565b925050602083013567ffffffffffffffff811115613b8157600080fd5b613b8d85828601613878565b9150509250929050565b60008060408385031215613baa57600080fd5b6000613bb8858286016138a2565b9250506020613bc9858286016138a2565b9150509250929050565b600080600060608486031215613be857600080fd5b6000613bf6868287016138a2565b9350506020613c07868287016138a2565b9250506040613c18868287016138a2565b9150509250925092565b613c2b8161497b565b82525050565b613c3a8161498d565b82525050565b6000613c4b82614818565b613c55818561482e565b9350613c65818560208601614a10565b613c6e81614bdc565b840191505092915050565b6000613c8482614818565b613c8e818561483f565b9350613c9e818560208601614a10565b80840191505092915050565b60008154613cb781614a43565b613cc1818661483f565b94506001821660008114613cdc5760018114613ced57613d20565b60ff19831686528186019350613d20565b613cf685614803565b60005b83811015613d1857815481890152600182019150602081019050613cf9565b838801955050505b50505092915050565b613d32816149ef565b82525050565b6000613d4382614823565b613d4d818561484a565b9350613d5d818560208601614a10565b613d6681614bdc565b840191505092915050565b6000613d7c82614823565b613d86818561485b565b9350613d96818560208601614a10565b80840191505092915050565b6000613daf60228361484a565b9150613dba82614bed565b604082019050919050565b6000613dd2601d8361484a565b9150613ddd82614c3c565b602082019050919050565b6000613df5601f8361484a565b9150613e0082614c65565b602082019050919050565b6000613e1860248361484a565b9150613e2382614c8e565b604082019050919050565b6000613e3b60328361484a565b9150613e4682614cdd565b604082019050919050565b6000613e5e60268361484a565b9150613e6982614d2c565b604082019050919050565b6000613e81601c8361484a565b9150613e8c82614d7b565b602082019050919050565b6000613ea460248361484a565b9150613eaf82614da4565b604082019050919050565b6000613ec760198361484a565b9150613ed282614df3565b602082019050919050565b6000613eea60268361484a565b9150613ef582614e1c565b604082019050919050565b6000613f0d602c8361484a565b9150613f1882614e6b565b604082019050919050565b6000613f3060168361484a565b9150613f3b82614eba565b602082019050919050565b6000613f5360388361484a565b9150613f5e82614ee3565b604082019050919050565b6000613f76602a8361484a565b9150613f8182614f32565b604082019050919050565b6000613f9960178361484a565b9150613fa482614f81565b602082019050919050565b6000613fbc60208361484a565b9150613fc782614faa565b602082019050919050565b6000613fdf60108361484a565b9150613fea82614fd3565b602082019050919050565b6000614002602c8361484a565b915061400d82614ffc565b604082019050919050565b600061402560208361484a565b91506140308261504b565b602082019050919050565b600061404860298361484a565b915061405382615074565b604082019050919050565b600061406b60218361484a565b9150614076826150c3565b604082019050919050565b600061408e60218361484a565b915061409982615112565b604082019050919050565b60006140b160208361484a565b91506140bc82615161565b602082019050919050565b60006140d460318361484a565b91506140df8261518a565b604082019050919050565b60006140f7601d8361484a565b9150614102826151d9565b602082019050919050565b600061411a60108361484a565b915061412582615202565b602082019050919050565b600061413d60308361484a565b91506141488261522b565b604082019050919050565b600061416060178361484a565b915061416b8261527a565b602082019050919050565b61417f816149e5565b82525050565b60006141918284613c79565b915081905092915050565b60006141a88284613caa565b915081905092915050565b60006141bf8285613d71565b91506141cb8284613d71565b91508190509392505050565b60006020820190506141ec6000830184613c22565b92915050565b60006060820190506142076000830186613c22565b6142146020830185613c22565b6142216040830184614176565b949350505050565b600060808201905061423e6000830187613c22565b61424b6020830186613c22565b6142586040830185614176565b818103606083015261426a8184613c40565b905095945050505050565b600060408201905061428a6000830185613c22565b818103602083015261429c8184613d38565b90509392505050565b60006040820190506142ba6000830185613c22565b6142c76020830184614176565b9392505050565b600060a0820190506142e36000830188613c22565b6142f06020830187614176565b6142fd6040830186613d29565b61430a6060830185614176565b6143176080830184614176565b9695505050505050565b600060a0820190506143366000830188613c22565b6143436020830187614176565b6143506040830186614176565b61435d6060830185614176565b61436a6080830184614176565b9695505050505050565b60006020820190506143896000830184613c31565b92915050565b600060208201905081810360008301526143a98184613d38565b905092915050565b600060208201905081810360008301526143ca81613da2565b9050919050565b600060208201905081810360008301526143ea81613dc5565b9050919050565b6000602082019050818103600083015261440a81613de8565b9050919050565b6000602082019050818103600083015261442a81613e0b565b9050919050565b6000602082019050818103600083015261444a81613e2e565b9050919050565b6000602082019050818103600083015261446a81613e51565b9050919050565b6000602082019050818103600083015261448a81613e74565b9050919050565b600060208201905081810360008301526144aa81613e97565b9050919050565b600060208201905081810360008301526144ca81613eba565b9050919050565b600060208201905081810360008301526144ea81613edd565b9050919050565b6000602082019050818103600083015261450a81613f00565b9050919050565b6000602082019050818103600083015261452a81613f23565b9050919050565b6000602082019050818103600083015261454a81613f46565b9050919050565b6000602082019050818103600083015261456a81613f69565b9050919050565b6000602082019050818103600083015261458a81613f8c565b9050919050565b600060208201905081810360008301526145aa81613faf565b9050919050565b600060208201905081810360008301526145ca81613fd2565b9050919050565b600060208201905081810360008301526145ea81613ff5565b9050919050565b6000602082019050818103600083015261460a81614018565b9050919050565b6000602082019050818103600083015261462a8161403b565b9050919050565b6000602082019050818103600083015261464a8161405e565b9050919050565b6000602082019050818103600083015261466a81614081565b9050919050565b6000602082019050818103600083015261468a816140a4565b9050919050565b600060208201905081810360008301526146aa816140c7565b9050919050565b600060208201905081810360008301526146ca816140ea565b9050919050565b600060208201905081810360008301526146ea8161410d565b9050919050565b6000602082019050818103600083015261470a81614130565b9050919050565b6000602082019050818103600083015261472a81614153565b9050919050565b60006020820190506147466000830184614176565b92915050565b60006040820190506147616000830185614176565b81810360208301526147738184613d38565b90509392505050565b6000614786614797565b90506147928282614a75565b919050565b6000604051905090565b600067ffffffffffffffff8211156147bc576147bb614bad565b5b6147c582614bdc565b9050602081019050919050565b600067ffffffffffffffff8211156147ed576147ec614bad565b5b6147f682614bdc565b9050602081019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000614871826149e5565b915061487c836149e5565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148b1576148b0614b20565b5b828201905092915050565b60006148c7826149e5565b91506148d2836149e5565b9250826148e2576148e1614b4f565b5b828204905092915050565b60006148f8826149e5565b9150614903836149e5565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561493c5761493b614b20565b5b828202905092915050565b6000614952826149e5565b915061495d836149e5565b9250828210156149705761496f614b20565b5b828203905092915050565b6000614986826149c5565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006149fa826149e5565b9050919050565b82818337600083830152505050565b60005b83811015614a2e578082015181840152602081019050614a13565b83811115614a3d576000848401525b50505050565b60006002820490506001821680614a5b57607f821691505b60208210811415614a6f57614a6e614b7e565b5b50919050565b614a7e82614bdc565b810181811067ffffffffffffffff82111715614a9d57614a9c614bad565b5b80604052505050565b6000614ab1826149e5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614ae457614ae3614b20565b5b600182019050919050565b6000614afa826149e5565b9150614b05836149e5565b925082614b1557614b14614b4f565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b7f6d6178696d756d206f6620313620537472696e6773206174206f6e6365000000600082015250565b7f4552433732313a2063616c6c6572206973206e6f7420746865206f776e657200600082015250565b7f7365656420616c726561647920757365642c2075736520616e6f74686572207360008201527f7461727400000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f64757374416d6f756e74206e6f7420636f727265637400000000000000000000600082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4e6f7420656e6f75676820537472696e6773206c656674000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f73656564206d6178203820627974657300000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552524f523a206e616d6520646f6573206e6f7420666f6c6c6f772072756c6560008201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552524f523a2063616e6e6f742072656d6f7665206475737420746f6b656e73600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f73656564207573656420616c7265647900000000000000000000000000000000600082015250565b7f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656400000000000000000000000000000000602082015250565b7f4552524f523a206e616d65206973207468652073616d65000000000000000000600082015250565b6152ac8161497b565b81146152b757600080fd5b50565b6152c38161498d565b81146152ce57600080fd5b50565b6152da81614999565b81146152e557600080fd5b50565b6152f1816149e5565b81146152fc57600080fd5b5056fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220c47a8998073a2bfa4162b558b65eebfd121b2643d8d1bb89957aac8a54e7d60b64736f6c63430008010033

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

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000424242115b5bbdc12a1f5c06dd8dd0ddd03c321d000000000000000000000000000000000000000000000000000000000000000c4149343320537472696e677300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006535452494e470000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : cname (string): AI43 Strings
Arg [1] : csymbol (string): STRING
Arg [2] : dustAddress (address): 0x424242115B5BbDc12A1f5C06Dd8DD0dDd03c321D

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 000000000000000000000000424242115b5bbdc12a1f5c06dd8dd0ddd03c321d
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [4] : 4149343320537472696e67730000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 535452494e470000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

1097:21038:16:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;523:188:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6451:90:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12660:209;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12218:381;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21627:506;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7001:127;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13508:300;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;11951:210;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6778:152;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11487:149;;;:::i;:::-;;11310:90;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13874:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7305:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11737:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;10112:452;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6222:167;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7534:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5954:211;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1693:145:14;;;:::i;:::-;;1409:69:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10775:448;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8973:1081;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7720:112;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1061:85:14;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6605:94:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12936:290;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1559:69;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14089:282;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7134:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8059:851;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5700:195;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1484:69;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5383:118;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7899:105;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13292:154;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1987:240:14;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;523:188:3;608:4;631:36;655:11;631:23;:36::i;:::-;:73;;;;671:20;:33;692:11;671:33;;;;;;;;;;;;;;;;;;;;;;;;;;;631:73;624:80;;523:188;;;:::o;6451:90:16:-;6497:13;6529:5;6522:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6451:90;:::o;12660:209::-;12728:7;12755:16;12763:7;12755;:16::i;:::-;12747:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;12838:15;:24;12854:7;12838:24;;;;;;;;;;;;;;;;;;;;;12831:31;;12660:209;;;:::o;12218:381::-;12298:13;12314:16;12322:7;12314;:16::i;:::-;12298:32;;12354:5;12348:11;;:2;:11;;;;12340:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;12432:5;12416:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;12441:37;12458:5;12465:12;:10;:12::i;:::-;12441:16;:37::i;:::-;12416:62;12408:152;;;;;;;;;;;;:::i;:::-;;;;;;;;;12571:21;12580:2;12584:7;12571:8;:21::i;:::-;12218:381;;;:::o;21627:506::-;21686:4;21701:14;21724:3;21701:27;;21754:1;21742;:8;:13;21738:31;;;21764:5;21757:12;;;;;21738:31;21807:2;21796:1;:8;:13;21792:31;;;21818:5;21811:12;;;;;21792:31;21862:4;21854:12;;:1;21856;21854:4;;;;;;;;;;;;;;;;;;;;;;;;:12;;;;21850:30;;;21875:5;21868:12;;;;;21850:30;21934:4;21915:23;;:1;21928;21917;:8;:12;;;;:::i;:::-;21915:15;;;;;;;;;;;;;;;;;;;;;;;;:23;;;;21911:41;;;21947:5;21940:12;;;;;21911:41;21988:6;21984:122;22000:1;:8;21996:1;:12;21984:122;;;22060:4;22053:11;;:1;22055;22053:4;;;;;;;;;;;;;;;;;;;;;;;;:11;;;;:26;;;;22075:4;22068:11;;:1;22070;22068:4;;;;;;;;;;;;;;;;;;;;;;;;:11;;;;22053:26;22049:46;;;22090:5;22083:12;;;;;;22049:46;22010:3;;;;;:::i;:::-;;;;21984:122;;;;22122:4;22115:11;;;21627:506;;;;:::o;7001:127::-;7054:7;7080:41;7106:14;;7080:21;:12;:19;:21::i;:::-;:25;;:41;;;;:::i;:::-;7073:48;;7001:127;:::o;13508:300::-;13667:41;13686:12;:10;:12::i;:::-;13700:7;13667:18;:41::i;:::-;13659:103;;;;;;;;;;;;:::i;:::-;;;;;;;;;13773:28;13783:4;13789:2;13793:7;13773:9;:28::i;:::-;13508:300;;;:::o;11951:210::-;1284:12:14;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;12056:12:16::1;;;;;;;;;;;12047:21;;:5;:21;;;;12039:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;12122:5;12115:22;;;12138:7;:5;:7::i;:::-;12147:6;12115:39;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;11951:210:::0;;:::o;6778:152::-;6867:7;6893:30;6917:5;6893:13;:20;6907:5;6893:20;;;;;;;;;;;;;;;:23;;:30;;;;:::i;:::-;6886:37;;6778:152;;;;:::o;11487:149::-;1284:12:14;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11536:24:16::1;11571:7;:5;:7::i;:::-;11536:43;;11589:8;:17;;:40;11607:21;11589:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;1343:1:14;11487:149:16:o:0;11310:90::-;1284:12:14;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11390:3:16::1;11377:10;:16;;;;11310:90:::0;:::o;13874:149::-;13977:39;13994:4;14000:2;14004:7;13977:39;;;;;;;;;;;;:16;:39::i;:::-;13874:149;;;:::o;7305:161::-;7372:7;7392:15;7413:22;7429:5;7413:12;:15;;:22;;;;:::i;:::-;7391:44;;;7452:7;7445:14;;;7305:161;;;:::o;11737:120::-;1284:12:14;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11811:12:16::1;;;;;;;;;;;11804:29;;;11834:7;:5;:7::i;:::-;11843:6;11804:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;11737:120:::0;:::o;10112:452::-;10221:16;10229:7;10221;:16::i;:::-;10205:32;;:12;:10;:12::i;:::-;:32;;;10197:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;10313:4;10291:26;;:18;10301:7;10291:9;:18::i;:::-;:26;;;10283:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;10418:10;:19;10429:7;10418:19;;;;;;;;;;;10402:37;;;;;;:::i;:::-;;;;;;;;10389:7;10373:25;;;;;;:66;;10365:102;;;;;;;;;;;;:::i;:::-;;;;;;;;;10500:7;10478:10;:19;10489:7;10478:19;;;;;;;;;;;:29;;;;;;;;;;;;:::i;:::-;;10522:35;10540:7;10549;10522:35;;;;;;;:::i;:::-;;;;;;;;10112:452;;:::o;6222:167::-;6286:7;6312:70;6329:7;6312:70;;;;;;;;;;;;;;;;;:12;:16;;:70;;;;;:::i;:::-;6305:77;;6222:167;;;:::o;7534:118::-;7596:13;7628:10;:17;7639:5;7628:17;;;;;;;;;;;7621:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7534:118;;;:::o;5954:211::-;6018:7;6062:1;6045:19;;:5;:19;;;;6037:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;6129:29;:13;:20;6143:5;6129:20;;;;;;;;;;;;;;;:27;:29::i;:::-;6122:36;;5954:211;;;:::o;1693:145:14:-;1284:12;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1799:1:::1;1762:40;;1783:6;::::0;::::1;;;;;;;;1762:40;;;;;;;;;;;;1829:1;1812:6:::0;::::1;:19;;;;;;;;;;;;;;;;;;1693:145::o:0;1409:69:16:-;1457:21;1409:69;:::o;10775:448::-;10916:41;10935:12;:10;:12::i;:::-;10949:7;10916:18;:41::i;:::-;10908:102;;;;;;;;;;;;:::i;:::-;;;;;;;;;11052:4;11028:28;;:20;11038:9;11028;:20::i;:::-;:28;;;11020:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;11126:9;11104:10;:19;11115:7;11104:19;;;;;;;;;;;:31;;;;;;;;;;;;:::i;:::-;;11145:14;11151:7;11145:5;:14::i;:::-;11183:7;11167:49;11192:12;:10;:12::i;:::-;11206:9;11167:49;;;;;;;:::i;:::-;;;;;;;;10775:448;;:::o;8973:1081::-;1457:21;9074:10;:34;9073:76;;;;1531:22;9114:10;:34;9073:76;:116;;;;1606:22;9154:10;:34;9073:116;9065:151;;;;;;;;;;;;:::i;:::-;;;;;;;;;9235:2;9227:5;:10;9219:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;9303:25;9322:5;9303:14;:12;:14::i;:::-;:18;;:25;;;;:::i;:::-;9289:10;;:39;;9281:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;9379:20;9367:9;:32;9359:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;9437:12;;;;;;;;;;;9431:32;;;9464:10;9484:4;9491:21;9506:5;9491:10;:14;;:21;;;;:::i;:::-;9431:82;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;9529:12;;;;;;;;;;;9523:24;;;9548:38;9582:3;9548:29;9574:2;9548:21;9563:5;9548:10;:14;;:21;;;;:::i;:::-;:25;;:29;;;;:::i;:::-;:33;;:38;;;;:::i;:::-;9523:64;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;9666:14;9683;:12;:14::i;:::-;9666:31;;9712:6;9707:260;9728:5;9724:1;:9;9707:260;;;9781:5;9755:31;;:9;:22;9775:1;9765:9;:11;;;;:::i;:::-;9755:22;;;;;;;;;;;;;;;;;;;;;:31;;;9747:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;9841:37;9851:10;9863:14;:12;:14::i;:::-;9841:9;:37::i;:::-;9910:4;9885:9;:22;9905:1;9895:9;:11;;;;:::i;:::-;9885:22;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;9955:1;9945:9;:11;;;;:::i;:::-;9921:10;:21;9932:9;9921:21;;;;;;;;;;;:35;;;;9735:3;;;;;:::i;:::-;;;;9707:260;;;;9981:66;9995:10;10007:9;10018:5;10025:10;10037:9;9981:66;;;;;;;;;;:::i;:::-;;;;;;;;8973:1081;;;;:::o;7720:112::-;7782:7;7808:10;:17;7819:5;7808:17;;;;;;;;;;;;7801:24;;7720:112;;;:::o;1061:85:14:-;1107:7;1133:6;;;;;;;;;;;1126:13;;1061:85;:::o;6605:94:16:-;6653:13;6685:7;6678:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6605:94;:::o;12936:290::-;13050:12;:10;:12::i;:::-;13038:24;;:8;:24;;;;13030:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;13148:8;13103:18;:32;13122:12;:10;:12::i;:::-;13103:32;;;;;;;;;;;;;;;:42;13136:8;13103:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;13200:8;13171:48;;13186:12;:10;:12::i;:::-;13171:48;;;13210:8;13171:48;;;;;;:::i;:::-;;;;;;;;12936:290;;:::o;1559:69::-;1606:22;1559:69;:::o;14089:282::-;14220:41;14239:12;:10;:12::i;:::-;14253:7;14220:18;:41::i;:::-;14212:103;;;;;;;;;;;;:::i;:::-;;;;;;;;;14325:39;14339:4;14345:2;14349:7;14358:5;14325:13;:39::i;:::-;14089:282;;;;:::o;7134:99::-;7179:7;7205:21;:12;:19;:21::i;:::-;7198:28;;7134:99;:::o;8059:851::-;8150:5;8131:24;;:9;:15;8141:4;8131:15;;;;;;;;;;;;;;;;;;;;;:24;;;8123:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;1457:21;8195:10;:34;8194:76;;;;1531:22;8235:10;:34;8194:76;:116;;;;1606:22;8275:10;:34;8194:116;8186:151;;;;;;;;;;;;:::i;:::-;;;;;;;;;8369:21;8388:1;8369:14;:12;:14::i;:::-;:18;;:21;;;;:::i;:::-;8355:10;;:35;;8347:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;8436:20;8429:4;:27;8421:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;8494:12;;;;;;;;;;;8488:32;;;8521:10;8541:4;8548:10;8488:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;8575:12;;;;;;;;;;;8569:24;;;8594:27;8617:3;8594:18;8609:2;8594:10;:14;;:18;;;;:::i;:::-;:22;;:27;;;;:::i;:::-;8569:53;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;8701:14;8718;:12;:14::i;:::-;8701:31;;8742:32;8752:10;8764:9;8742;:32::i;:::-;8795:4;8777:9;:15;8787:4;8777:15;;;;;;;;;;;;:22;;;;;;;;;;;;;;;;;;8826:4;8802:10;:21;8813:9;8802:21;;;;;;;;;;;:28;;;;8846:57;8860:10;8872:9;8883:1;8886:10;8898:4;8846:57;;;;;;;;;;:::i;:::-;;;;;;;;8059:851;;;:::o;5700:195::-;5758:13;5789:16;5797:7;5789;:16::i;:::-;5781:25;;;;;;5845:14;:12;:14::i;:::-;5861:25;5878:7;5861:16;:25::i;:::-;5828:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;5814:74;;5700:195;;;:::o;1484:69::-;1531:22;1484:69;:::o;5383:118::-;5428:13;5453:41;;;;;;;;;;;;;;;;;;;5383:118;:::o;7899:105::-;7954:4;7990:5;7971:24;;:9;:15;7981:4;7971:15;;;;;;;;;;;;;;;;;;;;;:24;;;7963:33;;7899:105;;;:::o;13292:154::-;13381:4;13404:18;:25;13423:5;13404:25;;;;;;;;;;;;;;;:35;13430:8;13404:35;;;;;;;;;;;;;;;;;;;;;;;;;13397:42;;13292:154;;;;:::o;1987:240:14:-;1284:12;:10;:12::i;:::-;1273:23;;:7;:5;:7::i;:::-;:23;;;1265:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2095:1:::1;2075:22;;:8;:22;;;;2067:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2184:8;2155:38;;2176:6;::::0;::::1;;;;;;;;2155:38;;;;;;;;;;;;2212:8;2203:6;::::0;:17:::1;;;;;;;;;;;;;;;;;;1987:240:::0;:::o;763:155:2:-;848:4;886:25;871:40;;;:11;:40;;;;864:47;;763:155;;;:::o;15805:117:16:-;15862:4;15885:30;15907:7;15885:12;:21;;:30;;;;:::i;:::-;15878:37;;15805:117;;;:::o;586:96:1:-;639:7;665:10;658:17;;586:96;:::o;20670:155:16:-;20762:2;20735:15;:24;20751:7;20735:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;20810:7;20806:2;20779:39;;20788:16;20796:7;20788;:16::i;:::-;20779:39;;;;;;;;;;;;20670:155;;:::o;5520:121:5:-;5589:7;5615:19;5623:3;:10;;5615:7;:19::i;:::-;5608:26;;5520:121;;;:::o;3148:96:15:-;3206:7;3236:1;3232;:5;;;;:::i;:::-;3225:12;;3148:96;;;;:::o;16080:329:16:-;16165:4;16189:16;16197:7;16189;:16::i;:::-;16181:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;16264:13;16280:16;16288:7;16280;:16::i;:::-;16264:32;;16325:5;16314:16;;:7;:16;;;:51;;;;16358:7;16334:31;;:20;16346:7;16334:11;:20::i;:::-;:31;;;16314:51;:87;;;;16369:32;16386:5;16393:7;16369:16;:32::i;:::-;16314:87;16306:96;;;16080:329;;;;:::o;18963:559::-;19080:4;19060:24;;:16;19068:7;19060;:16::i;:::-;:24;;;19052:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;19162:1;19148:16;;:2;:16;;;;19140:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;19216:39;19237:4;19243:2;19247:7;19216:20;:39::i;:::-;19317:29;19334:1;19338:7;19317:8;:29::i;:::-;19357:35;19384:7;19357:13;:19;19371:4;19357:19;;;;;;;;;;;;;;;:26;;:35;;;;:::i;:::-;;19402:30;19424:7;19402:13;:17;19416:2;19402:17;;;;;;;;;;;;;;;:21;;:30;;;;:::i;:::-;;19443:29;19460:7;19469:2;19443:12;:16;;:29;;;;;:::i;:::-;;19507:7;19503:2;19488:27;;19497:4;19488:27;;;;;;;;;;;;18963:559;;;:::o;9242:135:6:-;9313:7;9347:22;9351:3;:10;;9363:5;9347:3;:22::i;:::-;9339:31;;9332:38;;9242:135;;;;:::o;5969:233:5:-;6049:7;6058;6078:11;6091:13;6108:22;6112:3;:10;;6124:5;6108:3;:22::i;:::-;6077:53;;;;6156:3;6148:12;;6186:5;6178:14;;6140:55;;;;;;5969:233;;;;;:::o;7222:211::-;7329:7;7379:44;7384:3;:10;;7404:3;7396:12;;7410;7379:4;:44::i;:::-;7371:53;;7348:78;;7222:211;;;;;:::o;8798:112:6:-;8858:7;8884:19;8892:3;:10;;8884:7;:19::i;:::-;8877:26;;8798:112;;;:::o;18248:391:16:-;18307:13;18323:16;18331:7;18323;:16::i;:::-;18307:32;;18350:48;18371:5;18386:1;18390:7;18350:20;:48::i;:::-;18436:29;18453:1;18457:7;18436:8;:29::i;:::-;18476:36;18504:7;18476:13;:20;18490:5;18476:20;;;;;;;;;;;;;;;:27;;:36;;;;:::i;:::-;;18523:37;18540:7;18557:1;18523:12;:16;;:37;;;;;:::i;:::-;;18564:14;;:16;;;;;;;;;:::i;:::-;;;;;;18624:7;18620:1;18596:36;;18605:5;18596:36;;;;;;;;;;;;18248:391;;:::o;2781:96:15:-;2839:7;2869:1;2865;:5;;;;:::i;:::-;2858:12;;2781:96;;;;:::o;3491:::-;3549:7;3579:1;3575;:5;;;;:::i;:::-;3568:12;;3491:96;;;;:::o;3876:::-;3934:7;3964:1;3960;:5;;;;:::i;:::-;3953:12;;3876:96;;;;:::o;16740:108:16:-;16815:26;16825:2;16829:7;16815:26;;;;;;;;;;;;:9;:26::i;:::-;16740:108;;:::o;15233:269::-;15346:28;15356:4;15362:2;15366:7;15346:9;:28::i;:::-;15392:48;15415:4;15421:2;15425:7;15434:5;15392:22;:48::i;:::-;15384:111;;;;;;;;;;;;:::i;:::-;;;;;;;;;15233:269;;;;:::o;169:684:17:-;225:13;448:1;439:5;:10;435:49;;;464:10;;;;;;;;;;;;;;;;;;;;;435:49;492:12;507:5;492:20;;521:14;544:72;559:1;551:4;:9;544:72;;575:8;;;;;:::i;:::-;;;;604:2;596:10;;;;;:::i;:::-;;;544:72;;;624:19;656:6;646:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;624:39;;672:146;688:1;679:5;:10;672:146;;714:1;704:11;;;;;:::i;:::-;;;779:2;771:5;:10;;;;:::i;:::-;758:2;:24;;;;:::i;:::-;745:39;;728:6;735;728:14;;;;;;;;;;;;;;;;;;;:56;;;;;;;;;;;806:2;797:11;;;;;:::i;:::-;;;672:146;;;840:6;826:21;;;;;169:684;;;;:::o;5288:149:5:-;5372:4;5395:35;5405:3;:10;;5425:3;5417:12;;5395:9;:35::i;:::-;5388:42;;5288:149;;;;:::o;2462:107::-;2518:7;2544:18;:3;:9;;:16;:18::i;:::-;2537:25;;2462:107;;;:::o;21421:93:16:-;;;;:::o;8357:135:6:-;8427:4;8450:35;8458:3;:10;;8478:5;8470:14;;8450:7;:35::i;:::-;8443:42;;8357:135;;;;:::o;8060:129::-;8127:4;8150:32;8155:3;:10;;8175:5;8167:14;;8150:4;:32::i;:::-;8143:39;;8060:129;;;;:::o;4727:183:5:-;4816:4;4839:64;4844:3;:10;;4864:3;4856:12;;4894:5;4878:23;;4870:32;;4839:4;:64::i;:::-;4832:71;;4727:183;;;;;:::o;4444:201:6:-;4511:7;4559:5;4538:3;:11;;:18;;;;:26;4530:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;4620:3;:11;;4632:5;4620:18;;;;;;;;;;;;;;;;;;;;;;;;4613:25;;4444:201;;;;:::o;2912:175:5:-;2979:7;2988;3007:11;3021:19;3034:5;3021:3;:9;;:12;;:19;;;;:::i;:::-;3007:33;;3058:3;3063;:11;;:16;3075:3;3063:16;;;;;;;;;;;;3050:30;;;;;2912:175;;;;;:::o;4178:240::-;4272:7;4291:13;4307:3;:11;;:16;4319:3;4307:16;;;;;;;;;;;;4291:32;;4350:1;4341:10;;:5;:10;;:33;;;;4355:19;4365:3;4370;4355:9;:19::i;:::-;4341:33;4376:12;4333:56;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;4406:5;4399:12;;;4178:240;;;;;:::o;4005:107:6:-;4061:7;4087:3;:11;;:18;;;;4080:25;;4005:107;;;:::o;17069:247:16:-;17164:18;17170:2;17174:7;17164:5;:18::i;:::-;17200:54;17231:1;17235:2;17239:7;17248:5;17200:22;:54::i;:::-;17192:117;;;;;;;;;;;;:::i;:::-;;;;;;;;;17069:247;;;:::o;20075:589::-;20195:4;20220:15;:2;:13;;;:15::i;:::-;20215:58;;20258:4;20251:11;;;;20215:58;20282:23;20308:246;20360:45;;;20419:12;:10;:12::i;:::-;20445:4;20463:7;20484:5;20324:175;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20308:246;;;;;;;;;;;;;;;;;:2;:15;;;;:246;;;;;:::i;:::-;20282:272;;20564:13;20591:10;20580:32;;;;;;;;;;;;:::i;:::-;20564:48;;1850:10;20640:16;;20630:26;;;:6;:26;;;;20622:35;;;;20075:589;;;;;;;:::o;2248:124:5:-;2319:4;2342:23;2361:3;2342;:9;;:18;;:23;;;;:::i;:::-;2335:30;;2248:124;;;;:::o;5605:115:6:-;5668:7;5694:19;5702:3;:10;;5694:7;:19::i;:::-;5687:26;;5605:115;;;:::o;2204:1512::-;2270:4;2386:18;2407:3;:12;;:19;2420:5;2407:19;;;;;;;;;;;;2386:40;;2455:1;2441:10;:15;2437:1273;;2798:21;2835:1;2822:10;:14;;;;:::i;:::-;2798:38;;2850:17;2891:1;2870:3;:11;;:18;;;;:22;;;;:::i;:::-;2850:42;;3132:17;3152:3;:11;;3164:9;3152:22;;;;;;;;;;;;;;;;;;;;;;;;3132:42;;3295:9;3266:3;:11;;3278:13;3266:26;;;;;;;;;;;;;;;;;;;;;;;:38;;;;3412:1;3396:13;:17;;;;:::i;:::-;3370:3;:12;;:23;3383:9;3370:23;;;;;;;;;;;:43;;;;3519:3;:11;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3611:3;:12;;:19;3624:5;3611:19;;;;;;;;;;;3604:26;;;3652:4;3645:11;;;;;;;;2437:1273;3694:5;3687:12;;;2204:1512;;;;;:::o;1632:404::-;1695:4;1716:21;1726:3;1731:5;1716:9;:21::i;:::-;1711:319;;1753:3;:11;;1770:5;1753:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1933:3;:11;;:18;;;;1911:3;:12;;:19;1924:5;1911:19;;;;;;;;;;;:40;;;;1972:4;1965:11;;;;1711:319;2014:5;2007:12;;1632:404;;;;;:::o;1695:158:5:-;1771:4;1806:5;1787:3;:11;;:16;1799:3;1787:16;;;;;;;;;;;:24;;;;1828:18;1842:3;1828;:9;;:13;;:18;;;;:::i;:::-;1821:25;;1695:158;;;;;:::o;6052:129:6:-;6126:7;6152:22;6156:3;:10;;6168:5;6152:3;:22::i;:::-;6145:29;;6052:129;;;;:::o;17638:393:16:-;17731:1;17717:16;;:2;:16;;;;17709:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;17789:16;17797:7;17789;:16::i;:::-;17788:17;17780:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;17849:45;17878:1;17882:2;17886:7;17849:20;:45::i;:::-;17905:30;17927:7;17905:13;:17;17919:2;17905:17;;;;;;;;;;;;;;;:21;;:30;;;;:::i;:::-;;17946:29;17963:7;17972:2;17946:12;:16;;:29;;;;;:::i;:::-;;18016:7;18012:2;17991:33;;18008:1;17991:33;;;;;;;;;;;;17638:393;;:::o;822:413:0:-;882:4;1085:12;1194:7;1182:20;1174:28;;1227:1;1220:4;:8;1213:15;;;822:413;;;:::o;3677:193::-;3780:12;3811:52;3833:6;3841:4;3847:1;3850:12;3811:21;:52::i;:::-;3804:59;;3677:193;;;;;:::o;5386:138:6:-;5466:4;5489:28;5499:3;:10;;5511:5;5489:9;:28::i;:::-;5482:35;;5386:138;;;;:::o;3797:127::-;3870:4;3916:1;3893:3;:12;;:19;3906:5;3893:19;;;;;;;;;;;;:24;;3886:31;;3797:127;;;;:::o;4885:123::-;4955:4;4978:23;4983:3;:10;;4995:5;4978:4;:23::i;:::-;4971:30;;4885:123;;;;:::o;4704:523:0:-;4831:12;4888:5;4863:21;:30;;4855:81;;;;;;;;;;;;:::i;:::-;;;;;;;;;4954:18;4965:6;4954:10;:18::i;:::-;4946:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;5077:12;5091:23;5118:6;:11;;5138:5;5146:4;5118:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5076:75;;;;5168:52;5186:7;5195:10;5207:12;5168:17;:52::i;:::-;5161:59;;;;4704:523;;;;;;:::o;7187:725::-;7302:12;7330:7;7326:580;;;7360:10;7353:17;;;;7326:580;7491:1;7471:10;:17;:21;7467:429;;;7729:10;7723:17;7789:15;7776:10;7772:2;7768:19;7761:44;7678:145;7868:12;7861:20;;;;;;;;;;;:::i;:::-;;;;;;;;7187:725;;;;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:343:18:-;;109:65;125:48;166:6;125:48;:::i;:::-;109:65;:::i;:::-;100:74;;197:6;190:5;183:21;235:4;228:5;224:16;273:3;264:6;259:3;255:16;252:25;249:2;;;290:1;287;280:12;249:2;303:41;337:6;332:3;327;303:41;:::i;:::-;90:260;;;;;;:::o;356:345::-;;459:66;475:49;517:6;475:49;:::i;:::-;459:66;:::i;:::-;450:75;;548:6;541:5;534:21;586:4;579:5;575:16;624:3;615:6;610:3;606:16;603:25;600:2;;;641:1;638;631:12;600:2;654:41;688:6;683:3;678;654:41;:::i;:::-;440:261;;;;;;:::o;707:139::-;;791:6;778:20;769:29;;807:33;834:5;807:33;:::i;:::-;759:87;;;;:::o;852:133::-;;933:6;920:20;911:29;;949:30;973:5;949:30;:::i;:::-;901:84;;;;:::o;991:137::-;;1076:6;1070:13;1061:22;;1092:30;1116:5;1092:30;:::i;:::-;1051:77;;;;:::o;1134:137::-;;1217:6;1204:20;1195:29;;1233:32;1259:5;1233:32;:::i;:::-;1185:86;;;;:::o;1277:141::-;;1364:6;1358:13;1349:22;;1380:32;1406:5;1380:32;:::i;:::-;1339:79;;;;:::o;1437:271::-;;1541:3;1534:4;1526:6;1522:17;1518:27;1508:2;;1559:1;1556;1549:12;1508:2;1599:6;1586:20;1624:78;1698:3;1690:6;1683:4;1675:6;1671:17;1624:78;:::i;:::-;1615:87;;1498:210;;;;;:::o;1728:273::-;;1833:3;1826:4;1818:6;1814:17;1810:27;1800:2;;1851:1;1848;1841:12;1800:2;1891:6;1878:20;1916:79;1991:3;1983:6;1976:4;1968:6;1964:17;1916:79;:::i;:::-;1907:88;;1790:211;;;;;:::o;2007:139::-;;2091:6;2078:20;2069:29;;2107:33;2134:5;2107:33;:::i;:::-;2059:87;;;;:::o;2152:262::-;;2260:2;2248:9;2239:7;2235:23;2231:32;2228:2;;;2276:1;2273;2266:12;2228:2;2319:1;2344:53;2389:7;2380:6;2369:9;2365:22;2344:53;:::i;:::-;2334:63;;2290:117;2218:196;;;;:::o;2420:407::-;;;2545:2;2533:9;2524:7;2520:23;2516:32;2513:2;;;2561:1;2558;2551:12;2513:2;2604:1;2629:53;2674:7;2665:6;2654:9;2650:22;2629:53;:::i;:::-;2619:63;;2575:117;2731:2;2757:53;2802:7;2793:6;2782:9;2778:22;2757:53;:::i;:::-;2747:63;;2702:118;2503:324;;;;;:::o;2833:552::-;;;;2975:2;2963:9;2954:7;2950:23;2946:32;2943:2;;;2991:1;2988;2981:12;2943:2;3034:1;3059:53;3104:7;3095:6;3084:9;3080:22;3059:53;:::i;:::-;3049:63;;3005:117;3161:2;3187:53;3232:7;3223:6;3212:9;3208:22;3187:53;:::i;:::-;3177:63;;3132:118;3289:2;3315:53;3360:7;3351:6;3340:9;3336:22;3315:53;:::i;:::-;3305:63;;3260:118;2933:452;;;;;:::o;3391:809::-;;;;;3559:3;3547:9;3538:7;3534:23;3530:33;3527:2;;;3576:1;3573;3566:12;3527:2;3619:1;3644:53;3689:7;3680:6;3669:9;3665:22;3644:53;:::i;:::-;3634:63;;3590:117;3746:2;3772:53;3817:7;3808:6;3797:9;3793:22;3772:53;:::i;:::-;3762:63;;3717:118;3874:2;3900:53;3945:7;3936:6;3925:9;3921:22;3900:53;:::i;:::-;3890:63;;3845:118;4030:2;4019:9;4015:18;4002:32;4061:18;4053:6;4050:30;4047:2;;;4093:1;4090;4083:12;4047:2;4121:62;4175:7;4166:6;4155:9;4151:22;4121:62;:::i;:::-;4111:72;;3973:220;3517:683;;;;;;;:::o;4206:401::-;;;4328:2;4316:9;4307:7;4303:23;4299:32;4296:2;;;4344:1;4341;4334:12;4296:2;4387:1;4412:53;4457:7;4448:6;4437:9;4433:22;4412:53;:::i;:::-;4402:63;;4358:117;4514:2;4540:50;4582:7;4573:6;4562:9;4558:22;4540:50;:::i;:::-;4530:60;;4485:115;4286:321;;;;;:::o;4613:407::-;;;4738:2;4726:9;4717:7;4713:23;4709:32;4706:2;;;4754:1;4751;4744:12;4706:2;4797:1;4822:53;4867:7;4858:6;4847:9;4843:22;4822:53;:::i;:::-;4812:63;;4768:117;4924:2;4950:53;4995:7;4986:6;4975:9;4971:22;4950:53;:::i;:::-;4940:63;;4895:118;4696:324;;;;;:::o;5026:278::-;;5142:2;5130:9;5121:7;5117:23;5113:32;5110:2;;;5158:1;5155;5148:12;5110:2;5201:1;5226:61;5279:7;5270:6;5259:9;5255:22;5226:61;:::i;:::-;5216:71;;5172:125;5100:204;;;;:::o;5310:260::-;;5417:2;5405:9;5396:7;5392:23;5388:32;5385:2;;;5433:1;5430;5423:12;5385:2;5476:1;5501:52;5545:7;5536:6;5525:9;5521:22;5501:52;:::i;:::-;5491:62;;5447:116;5375:195;;;;:::o;5576:282::-;;5694:2;5682:9;5673:7;5669:23;5665:32;5662:2;;;5710:1;5707;5700:12;5662:2;5753:1;5778:63;5833:7;5824:6;5813:9;5809:22;5778:63;:::i;:::-;5768:73;;5724:127;5652:206;;;;:::o;5864:375::-;;5982:2;5970:9;5961:7;5957:23;5953:32;5950:2;;;5998:1;5995;5988:12;5950:2;6069:1;6058:9;6054:17;6041:31;6099:18;6091:6;6088:30;6085:2;;;6131:1;6128;6121:12;6085:2;6159:63;6214:7;6205:6;6194:9;6190:22;6159:63;:::i;:::-;6149:73;;6012:220;5940:299;;;;:::o;6245:262::-;;6353:2;6341:9;6332:7;6328:23;6324:32;6321:2;;;6369:1;6366;6359:12;6321:2;6412:1;6437:53;6482:7;6473:6;6462:9;6458:22;6437:53;:::i;:::-;6427:63;;6383:117;6311:196;;;;:::o;6513:520::-;;;6648:2;6636:9;6627:7;6623:23;6619:32;6616:2;;;6664:1;6661;6654:12;6616:2;6707:1;6732:53;6777:7;6768:6;6757:9;6753:22;6732:53;:::i;:::-;6722:63;;6678:117;6862:2;6851:9;6847:18;6834:32;6893:18;6885:6;6882:30;6879:2;;;6925:1;6922;6915:12;6879:2;6953:63;7008:7;6999:6;6988:9;6984:22;6953:63;:::i;:::-;6943:73;;6805:221;6606:427;;;;;:::o;7039:407::-;;;7164:2;7152:9;7143:7;7139:23;7135:32;7132:2;;;7180:1;7177;7170:12;7132:2;7223:1;7248:53;7293:7;7284:6;7273:9;7269:22;7248:53;:::i;:::-;7238:63;;7194:117;7350:2;7376:53;7421:7;7412:6;7401:9;7397:22;7376:53;:::i;:::-;7366:63;;7321:118;7122:324;;;;;:::o;7452:552::-;;;;7594:2;7582:9;7573:7;7569:23;7565:32;7562:2;;;7610:1;7607;7600:12;7562:2;7653:1;7678:53;7723:7;7714:6;7703:9;7699:22;7678:53;:::i;:::-;7668:63;;7624:117;7780:2;7806:53;7851:7;7842:6;7831:9;7827:22;7806:53;:::i;:::-;7796:63;;7751:118;7908:2;7934:53;7979:7;7970:6;7959:9;7955:22;7934:53;:::i;:::-;7924:63;;7879:118;7552:452;;;;;:::o;8010:118::-;8097:24;8115:5;8097:24;:::i;:::-;8092:3;8085:37;8075:53;;:::o;8134:109::-;8215:21;8230:5;8215:21;:::i;:::-;8210:3;8203:34;8193:50;;:::o;8249:360::-;;8363:38;8395:5;8363:38;:::i;:::-;8417:70;8480:6;8475:3;8417:70;:::i;:::-;8410:77;;8496:52;8541:6;8536:3;8529:4;8522:5;8518:16;8496:52;:::i;:::-;8573:29;8595:6;8573:29;:::i;:::-;8568:3;8564:39;8557:46;;8339:270;;;;;:::o;8615:373::-;;8747:38;8779:5;8747:38;:::i;:::-;8801:88;8882:6;8877:3;8801:88;:::i;:::-;8794:95;;8898:52;8943:6;8938:3;8931:4;8924:5;8920:16;8898:52;:::i;:::-;8975:6;8970:3;8966:16;8959:23;;8723:265;;;;;:::o;9016:849::-;;9158:5;9152:12;9187:36;9213:9;9187:36;:::i;:::-;9239:88;9320:6;9315:3;9239:88;:::i;:::-;9232:95;;9358:1;9347:9;9343:17;9374:1;9369:137;;;;9520:1;9515:344;;;;9336:523;;9369:137;9453:4;9449:9;9438;9434:25;9429:3;9422:38;9489:6;9484:3;9480:16;9473:23;;9369:137;;9515:344;9582:41;9617:5;9582:41;:::i;:::-;9645:1;9659:154;9673:6;9670:1;9667:13;9659:154;;;9747:7;9741:14;9737:1;9732:3;9728:11;9721:35;9797:1;9788:7;9784:15;9773:26;;9695:4;9692:1;9688:12;9683:17;;9659:154;;;9842:6;9837:3;9833:16;9826:23;;9522:337;;9336:523;;9125:740;;;;;;:::o;9871:147::-;9966:45;10005:5;9966:45;:::i;:::-;9961:3;9954:58;9944:74;;:::o;10024:364::-;;10140:39;10173:5;10140:39;:::i;:::-;10195:71;10259:6;10254:3;10195:71;:::i;:::-;10188:78;;10275:52;10320:6;10315:3;10308:4;10301:5;10297:16;10275:52;:::i;:::-;10352:29;10374:6;10352:29;:::i;:::-;10347:3;10343:39;10336:46;;10116:272;;;;;:::o;10394:377::-;;10528:39;10561:5;10528:39;:::i;:::-;10583:89;10665:6;10660:3;10583:89;:::i;:::-;10576:96;;10681:52;10726:6;10721:3;10714:4;10707:5;10703:16;10681:52;:::i;:::-;10758:6;10753:3;10749:16;10742:23;;10504:267;;;;;:::o;10777:366::-;;10940:67;11004:2;10999:3;10940:67;:::i;:::-;10933:74;;11016:93;11105:3;11016:93;:::i;:::-;11134:2;11129:3;11125:12;11118:19;;10923:220;;;:::o;11149:366::-;;11312:67;11376:2;11371:3;11312:67;:::i;:::-;11305:74;;11388:93;11477:3;11388:93;:::i;:::-;11506:2;11501:3;11497:12;11490:19;;11295:220;;;:::o;11521:366::-;;11684:67;11748:2;11743:3;11684:67;:::i;:::-;11677:74;;11760:93;11849:3;11760:93;:::i;:::-;11878:2;11873:3;11869:12;11862:19;;11667:220;;;:::o;11893:366::-;;12056:67;12120:2;12115:3;12056:67;:::i;:::-;12049:74;;12132:93;12221:3;12132:93;:::i;:::-;12250:2;12245:3;12241:12;12234:19;;12039:220;;;:::o;12265:366::-;;12428:67;12492:2;12487:3;12428:67;:::i;:::-;12421:74;;12504:93;12593:3;12504:93;:::i;:::-;12622:2;12617:3;12613:12;12606:19;;12411:220;;;:::o;12637:366::-;;12800:67;12864:2;12859:3;12800:67;:::i;:::-;12793:74;;12876:93;12965:3;12876:93;:::i;:::-;12994:2;12989:3;12985:12;12978:19;;12783:220;;;:::o;13009:366::-;;13172:67;13236:2;13231:3;13172:67;:::i;:::-;13165:74;;13248:93;13337:3;13248:93;:::i;:::-;13366:2;13361:3;13357:12;13350:19;;13155:220;;;:::o;13381:366::-;;13544:67;13608:2;13603:3;13544:67;:::i;:::-;13537:74;;13620:93;13709:3;13620:93;:::i;:::-;13738:2;13733:3;13729:12;13722:19;;13527:220;;;:::o;13753:366::-;;13916:67;13980:2;13975:3;13916:67;:::i;:::-;13909:74;;13992:93;14081:3;13992:93;:::i;:::-;14110:2;14105:3;14101:12;14094:19;;13899:220;;;:::o;14125:366::-;;14288:67;14352:2;14347:3;14288:67;:::i;:::-;14281:74;;14364:93;14453:3;14364:93;:::i;:::-;14482:2;14477:3;14473:12;14466:19;;14271:220;;;:::o;14497:366::-;;14660:67;14724:2;14719:3;14660:67;:::i;:::-;14653:74;;14736:93;14825:3;14736:93;:::i;:::-;14854:2;14849:3;14845:12;14838:19;;14643:220;;;:::o;14869:366::-;;15032:67;15096:2;15091:3;15032:67;:::i;:::-;15025:74;;15108:93;15197:3;15108:93;:::i;:::-;15226:2;15221:3;15217:12;15210:19;;15015:220;;;:::o;15241:366::-;;15404:67;15468:2;15463:3;15404:67;:::i;:::-;15397:74;;15480:93;15569:3;15480:93;:::i;:::-;15598:2;15593:3;15589:12;15582:19;;15387:220;;;:::o;15613:366::-;;15776:67;15840:2;15835:3;15776:67;:::i;:::-;15769:74;;15852:93;15941:3;15852:93;:::i;:::-;15970:2;15965:3;15961:12;15954:19;;15759:220;;;:::o;15985:366::-;;16148:67;16212:2;16207:3;16148:67;:::i;:::-;16141:74;;16224:93;16313:3;16224:93;:::i;:::-;16342:2;16337:3;16333:12;16326:19;;16131:220;;;:::o;16357:366::-;;16520:67;16584:2;16579:3;16520:67;:::i;:::-;16513:74;;16596:93;16685:3;16596:93;:::i;:::-;16714:2;16709:3;16705:12;16698:19;;16503:220;;;:::o;16729:366::-;;16892:67;16956:2;16951:3;16892:67;:::i;:::-;16885:74;;16968:93;17057:3;16968:93;:::i;:::-;17086:2;17081:3;17077:12;17070:19;;16875:220;;;:::o;17101:366::-;;17264:67;17328:2;17323:3;17264:67;:::i;:::-;17257:74;;17340:93;17429:3;17340:93;:::i;:::-;17458:2;17453:3;17449:12;17442:19;;17247:220;;;:::o;17473:366::-;;17636:67;17700:2;17695:3;17636:67;:::i;:::-;17629:74;;17712:93;17801:3;17712:93;:::i;:::-;17830:2;17825:3;17821:12;17814:19;;17619:220;;;:::o;17845:366::-;;18008:67;18072:2;18067:3;18008:67;:::i;:::-;18001:74;;18084:93;18173:3;18084:93;:::i;:::-;18202:2;18197:3;18193:12;18186:19;;17991:220;;;:::o;18217:366::-;;18380:67;18444:2;18439:3;18380:67;:::i;:::-;18373:74;;18456:93;18545:3;18456:93;:::i;:::-;18574:2;18569:3;18565:12;18558:19;;18363:220;;;:::o;18589:366::-;;18752:67;18816:2;18811:3;18752:67;:::i;:::-;18745:74;;18828:93;18917:3;18828:93;:::i;:::-;18946:2;18941:3;18937:12;18930:19;;18735:220;;;:::o;18961:366::-;;19124:67;19188:2;19183:3;19124:67;:::i;:::-;19117:74;;19200:93;19289:3;19200:93;:::i;:::-;19318:2;19313:3;19309:12;19302:19;;19107:220;;;:::o;19333:366::-;;19496:67;19560:2;19555:3;19496:67;:::i;:::-;19489:74;;19572:93;19661:3;19572:93;:::i;:::-;19690:2;19685:3;19681:12;19674:19;;19479:220;;;:::o;19705:366::-;;19868:67;19932:2;19927:3;19868:67;:::i;:::-;19861:74;;19944:93;20033:3;19944:93;:::i;:::-;20062:2;20057:3;20053:12;20046:19;;19851:220;;;:::o;20077:366::-;;20240:67;20304:2;20299:3;20240:67;:::i;:::-;20233:74;;20316:93;20405:3;20316:93;:::i;:::-;20434:2;20429:3;20425:12;20418:19;;20223:220;;;:::o;20449:366::-;;20612:67;20676:2;20671:3;20612:67;:::i;:::-;20605:74;;20688:93;20777:3;20688:93;:::i;:::-;20806:2;20801:3;20797:12;20790:19;;20595:220;;;:::o;20821:366::-;;20984:67;21048:2;21043:3;20984:67;:::i;:::-;20977:74;;21060:93;21149:3;21060:93;:::i;:::-;21178:2;21173:3;21169:12;21162:19;;20967:220;;;:::o;21193:118::-;21280:24;21298:5;21280:24;:::i;:::-;21275:3;21268:37;21258:53;;:::o;21317:271::-;;21469:93;21558:3;21549:6;21469:93;:::i;:::-;21462:100;;21579:3;21572:10;;21451:137;;;;:::o;21594:273::-;;21747:94;21837:3;21828:6;21747:94;:::i;:::-;21740:101;;21858:3;21851:10;;21729:138;;;;:::o;21873:435::-;;22075:95;22166:3;22157:6;22075:95;:::i;:::-;22068:102;;22187:95;22278:3;22269:6;22187:95;:::i;:::-;22180:102;;22299:3;22292:10;;22057:251;;;;;:::o;22314:222::-;;22445:2;22434:9;22430:18;22422:26;;22458:71;22526:1;22515:9;22511:17;22502:6;22458:71;:::i;:::-;22412:124;;;;:::o;22542:442::-;;22729:2;22718:9;22714:18;22706:26;;22742:71;22810:1;22799:9;22795:17;22786:6;22742:71;:::i;:::-;22823:72;22891:2;22880:9;22876:18;22867:6;22823:72;:::i;:::-;22905;22973:2;22962:9;22958:18;22949:6;22905:72;:::i;:::-;22696:288;;;;;;:::o;22990:640::-;;23223:3;23212:9;23208:19;23200:27;;23237:71;23305:1;23294:9;23290:17;23281:6;23237:71;:::i;:::-;23318:72;23386:2;23375:9;23371:18;23362:6;23318:72;:::i;:::-;23400;23468:2;23457:9;23453:18;23444:6;23400:72;:::i;:::-;23519:9;23513:4;23509:20;23504:2;23493:9;23489:18;23482:48;23547:76;23618:4;23609:6;23547:76;:::i;:::-;23539:84;;23190:440;;;;;;;:::o;23636:423::-;;23815:2;23804:9;23800:18;23792:26;;23828:71;23896:1;23885:9;23881:17;23872:6;23828:71;:::i;:::-;23946:9;23940:4;23936:20;23931:2;23920:9;23916:18;23909:48;23974:78;24047:4;24038:6;23974:78;:::i;:::-;23966:86;;23782:277;;;;;:::o;24065:332::-;;24224:2;24213:9;24209:18;24201:26;;24237:71;24305:1;24294:9;24290:17;24281:6;24237:71;:::i;:::-;24318:72;24386:2;24375:9;24371:18;24362:6;24318:72;:::i;:::-;24191:206;;;;;:::o;24403:680::-;;24654:3;24643:9;24639:19;24631:27;;24668:71;24736:1;24725:9;24721:17;24712:6;24668:71;:::i;:::-;24749:72;24817:2;24806:9;24802:18;24793:6;24749:72;:::i;:::-;24831:80;24907:2;24896:9;24892:18;24883:6;24831:80;:::i;:::-;24921:72;24989:2;24978:9;24974:18;24965:6;24921:72;:::i;:::-;25003:73;25071:3;25060:9;25056:19;25047:6;25003:73;:::i;:::-;24621:462;;;;;;;;:::o;25089:664::-;;25332:3;25321:9;25317:19;25309:27;;25346:71;25414:1;25403:9;25399:17;25390:6;25346:71;:::i;:::-;25427:72;25495:2;25484:9;25480:18;25471:6;25427:72;:::i;:::-;25509;25577:2;25566:9;25562:18;25553:6;25509:72;:::i;:::-;25591;25659:2;25648:9;25644:18;25635:6;25591:72;:::i;:::-;25673:73;25741:3;25730:9;25726:19;25717:6;25673:73;:::i;:::-;25299:454;;;;;;;;:::o;25759:210::-;;25884:2;25873:9;25869:18;25861:26;;25897:65;25959:1;25948:9;25944:17;25935:6;25897:65;:::i;:::-;25851:118;;;;:::o;25975:313::-;;26126:2;26115:9;26111:18;26103:26;;26175:9;26169:4;26165:20;26161:1;26150:9;26146:17;26139:47;26203:78;26276:4;26267:6;26203:78;:::i;:::-;26195:86;;26093:195;;;;:::o;26294:419::-;;26498:2;26487:9;26483:18;26475:26;;26547:9;26541:4;26537:20;26533:1;26522:9;26518:17;26511:47;26575:131;26701:4;26575:131;:::i;:::-;26567:139;;26465:248;;;:::o;26719:419::-;;26923:2;26912:9;26908:18;26900:26;;26972:9;26966:4;26962:20;26958:1;26947:9;26943:17;26936:47;27000:131;27126:4;27000:131;:::i;:::-;26992:139;;26890:248;;;:::o;27144:419::-;;27348:2;27337:9;27333:18;27325:26;;27397:9;27391:4;27387:20;27383:1;27372:9;27368:17;27361:47;27425:131;27551:4;27425:131;:::i;:::-;27417:139;;27315:248;;;:::o;27569:419::-;;27773:2;27762:9;27758:18;27750:26;;27822:9;27816:4;27812:20;27808:1;27797:9;27793:17;27786:47;27850:131;27976:4;27850:131;:::i;:::-;27842:139;;27740:248;;;:::o;27994:419::-;;28198:2;28187:9;28183:18;28175:26;;28247:9;28241:4;28237:20;28233:1;28222:9;28218:17;28211:47;28275:131;28401:4;28275:131;:::i;:::-;28267:139;;28165:248;;;:::o;28419:419::-;;28623:2;28612:9;28608:18;28600:26;;28672:9;28666:4;28662:20;28658:1;28647:9;28643:17;28636:47;28700:131;28826:4;28700:131;:::i;:::-;28692:139;;28590:248;;;:::o;28844:419::-;;29048:2;29037:9;29033:18;29025:26;;29097:9;29091:4;29087:20;29083:1;29072:9;29068:17;29061:47;29125:131;29251:4;29125:131;:::i;:::-;29117:139;;29015:248;;;:::o;29269:419::-;;29473:2;29462:9;29458:18;29450:26;;29522:9;29516:4;29512:20;29508:1;29497:9;29493:17;29486:47;29550:131;29676:4;29550:131;:::i;:::-;29542:139;;29440:248;;;:::o;29694:419::-;;29898:2;29887:9;29883:18;29875:26;;29947:9;29941:4;29937:20;29933:1;29922:9;29918:17;29911:47;29975:131;30101:4;29975:131;:::i;:::-;29967:139;;29865:248;;;:::o;30119:419::-;;30323:2;30312:9;30308:18;30300:26;;30372:9;30366:4;30362:20;30358:1;30347:9;30343:17;30336:47;30400:131;30526:4;30400:131;:::i;:::-;30392:139;;30290:248;;;:::o;30544:419::-;;30748:2;30737:9;30733:18;30725:26;;30797:9;30791:4;30787:20;30783:1;30772:9;30768:17;30761:47;30825:131;30951:4;30825:131;:::i;:::-;30817:139;;30715:248;;;:::o;30969:419::-;;31173:2;31162:9;31158:18;31150:26;;31222:9;31216:4;31212:20;31208:1;31197:9;31193:17;31186:47;31250:131;31376:4;31250:131;:::i;:::-;31242:139;;31140:248;;;:::o;31394:419::-;;31598:2;31587:9;31583:18;31575:26;;31647:9;31641:4;31637:20;31633:1;31622:9;31618:17;31611:47;31675:131;31801:4;31675:131;:::i;:::-;31667:139;;31565:248;;;:::o;31819:419::-;;32023:2;32012:9;32008:18;32000:26;;32072:9;32066:4;32062:20;32058:1;32047:9;32043:17;32036:47;32100:131;32226:4;32100:131;:::i;:::-;32092:139;;31990:248;;;:::o;32244:419::-;;32448:2;32437:9;32433:18;32425:26;;32497:9;32491:4;32487:20;32483:1;32472:9;32468:17;32461:47;32525:131;32651:4;32525:131;:::i;:::-;32517:139;;32415:248;;;:::o;32669:419::-;;32873:2;32862:9;32858:18;32850:26;;32922:9;32916:4;32912:20;32908:1;32897:9;32893:17;32886:47;32950:131;33076:4;32950:131;:::i;:::-;32942:139;;32840:248;;;:::o;33094:419::-;;33298:2;33287:9;33283:18;33275:26;;33347:9;33341:4;33337:20;33333:1;33322:9;33318:17;33311:47;33375:131;33501:4;33375:131;:::i;:::-;33367:139;;33265:248;;;:::o;33519:419::-;;33723:2;33712:9;33708:18;33700:26;;33772:9;33766:4;33762:20;33758:1;33747:9;33743:17;33736:47;33800:131;33926:4;33800:131;:::i;:::-;33792:139;;33690:248;;;:::o;33944:419::-;;34148:2;34137:9;34133:18;34125:26;;34197:9;34191:4;34187:20;34183:1;34172:9;34168:17;34161:47;34225:131;34351:4;34225:131;:::i;:::-;34217:139;;34115:248;;;:::o;34369:419::-;;34573:2;34562:9;34558:18;34550:26;;34622:9;34616:4;34612:20;34608:1;34597:9;34593:17;34586:47;34650:131;34776:4;34650:131;:::i;:::-;34642:139;;34540:248;;;:::o;34794:419::-;;34998:2;34987:9;34983:18;34975:26;;35047:9;35041:4;35037:20;35033:1;35022:9;35018:17;35011:47;35075:131;35201:4;35075:131;:::i;:::-;35067:139;;34965:248;;;:::o;35219:419::-;;35423:2;35412:9;35408:18;35400:26;;35472:9;35466:4;35462:20;35458:1;35447:9;35443:17;35436:47;35500:131;35626:4;35500:131;:::i;:::-;35492:139;;35390:248;;;:::o;35644:419::-;;35848:2;35837:9;35833:18;35825:26;;35897:9;35891:4;35887:20;35883:1;35872:9;35868:17;35861:47;35925:131;36051:4;35925:131;:::i;:::-;35917:139;;35815:248;;;:::o;36069:419::-;;36273:2;36262:9;36258:18;36250:26;;36322:9;36316:4;36312:20;36308:1;36297:9;36293:17;36286:47;36350:131;36476:4;36350:131;:::i;:::-;36342:139;;36240:248;;;:::o;36494:419::-;;36698:2;36687:9;36683:18;36675:26;;36747:9;36741:4;36737:20;36733:1;36722:9;36718:17;36711:47;36775:131;36901:4;36775:131;:::i;:::-;36767:139;;36665:248;;;:::o;36919:419::-;;37123:2;37112:9;37108:18;37100:26;;37172:9;37166:4;37162:20;37158:1;37147:9;37143:17;37136:47;37200:131;37326:4;37200:131;:::i;:::-;37192:139;;37090:248;;;:::o;37344:419::-;;37548:2;37537:9;37533:18;37525:26;;37597:9;37591:4;37587:20;37583:1;37572:9;37568:17;37561:47;37625:131;37751:4;37625:131;:::i;:::-;37617:139;;37515:248;;;:::o;37769:419::-;;37973:2;37962:9;37958:18;37950:26;;38022:9;38016:4;38012:20;38008:1;37997:9;37993:17;37986:47;38050:131;38176:4;38050:131;:::i;:::-;38042:139;;37940:248;;;:::o;38194:222::-;;38325:2;38314:9;38310:18;38302:26;;38338:71;38406:1;38395:9;38391:17;38382:6;38338:71;:::i;:::-;38292:124;;;;:::o;38422:423::-;;38601:2;38590:9;38586:18;38578:26;;38614:71;38682:1;38671:9;38667:17;38658:6;38614:71;:::i;:::-;38732:9;38726:4;38722:20;38717:2;38706:9;38702:18;38695:48;38760:78;38833:4;38824:6;38760:78;:::i;:::-;38752:86;;38568:277;;;;;:::o;38851:129::-;;38912:20;;:::i;:::-;38902:30;;38941:33;38969:4;38961:6;38941:33;:::i;:::-;38892:88;;;:::o;38986:75::-;;39052:2;39046:9;39036:19;;39026:35;:::o;39067:307::-;;39218:18;39210:6;39207:30;39204:2;;;39240:18;;:::i;:::-;39204:2;39278:29;39300:6;39278:29;:::i;:::-;39270:37;;39362:4;39356;39352:15;39344:23;;39133:241;;;:::o;39380:308::-;;39532:18;39524:6;39521:30;39518:2;;;39554:18;;:::i;:::-;39518:2;39592:29;39614:6;39592:29;:::i;:::-;39584:37;;39676:4;39670;39666:15;39658:23;;39447:241;;;:::o;39694:144::-;;39769:3;39761:11;;39792:3;39789:1;39782:14;39826:4;39823:1;39813:18;39805:26;;39751:87;;;:::o;39844:98::-;;39929:5;39923:12;39913:22;;39902:40;;;:::o;39948:99::-;;40034:5;40028:12;40018:22;;40007:40;;;:::o;40053:168::-;;40170:6;40165:3;40158:19;40210:4;40205:3;40201:14;40186:29;;40148:73;;;;:::o;40227:147::-;;40365:3;40350:18;;40340:34;;;;:::o;40380:169::-;;40498:6;40493:3;40486:19;40538:4;40533:3;40529:14;40514:29;;40476:73;;;;:::o;40555:148::-;;40694:3;40679:18;;40669:34;;;;:::o;40709:305::-;;40768:20;40786:1;40768:20;:::i;:::-;40763:25;;40802:20;40820:1;40802:20;:::i;:::-;40797:25;;40956:1;40888:66;40884:74;40881:1;40878:81;40875:2;;;40962:18;;:::i;:::-;40875:2;41006:1;41003;40999:9;40992:16;;40753:261;;;;:::o;41020:185::-;;41077:20;41095:1;41077:20;:::i;:::-;41072:25;;41111:20;41129:1;41111:20;:::i;:::-;41106:25;;41150:1;41140:2;;41155:18;;:::i;:::-;41140:2;41197:1;41194;41190:9;41185:14;;41062:143;;;;:::o;41211:348::-;;41274:20;41292:1;41274:20;:::i;:::-;41269:25;;41308:20;41326:1;41308:20;:::i;:::-;41303:25;;41496:1;41428:66;41424:74;41421:1;41418:81;41413:1;41406:9;41399:17;41395:105;41392:2;;;41503:18;;:::i;:::-;41392:2;41551:1;41548;41544:9;41533:20;;41259:300;;;;:::o;41565:191::-;;41625:20;41643:1;41625:20;:::i;:::-;41620:25;;41659:20;41677:1;41659:20;:::i;:::-;41654:25;;41698:1;41695;41692:8;41689:2;;;41703:18;;:::i;:::-;41689:2;41748:1;41745;41741:9;41733:17;;41610:146;;;;:::o;41762:96::-;;41828:24;41846:5;41828:24;:::i;:::-;41817:35;;41807:51;;;:::o;41864:90::-;;41941:5;41934:13;41927:21;41916:32;;41906:48;;;:::o;41960:149::-;;42036:66;42029:5;42025:78;42014:89;;42004:105;;;:::o;42115:126::-;;42192:42;42185:5;42181:54;42170:65;;42160:81;;;:::o;42247:77::-;;42313:5;42302:16;;42292:32;;;:::o;42330:121::-;;42421:24;42439:5;42421:24;:::i;:::-;42408:37;;42398:53;;;:::o;42457:154::-;42541:6;42536:3;42531;42518:30;42603:1;42594:6;42589:3;42585:16;42578:27;42508:103;;;:::o;42617:307::-;42685:1;42695:113;42709:6;42706:1;42703:13;42695:113;;;42794:1;42789:3;42785:11;42779:18;42775:1;42770:3;42766:11;42759:39;42731:2;42728:1;42724:10;42719:15;;42695:113;;;42826:6;42823:1;42820:13;42817:2;;;42906:1;42897:6;42892:3;42888:16;42881:27;42817:2;42666:258;;;;:::o;42930:320::-;;43011:1;43005:4;43001:12;42991:22;;43058:1;43052:4;43048:12;43079:18;43069:2;;43135:4;43127:6;43123:17;43113:27;;43069:2;43197;43189:6;43186:14;43166:18;43163:38;43160:2;;;43216:18;;:::i;:::-;43160:2;42981:269;;;;:::o;43256:281::-;43339:27;43361:4;43339:27;:::i;:::-;43331:6;43327:40;43469:6;43457:10;43454:22;43433:18;43421:10;43418:34;43415:62;43412:2;;;43480:18;;:::i;:::-;43412:2;43520:10;43516:2;43509:22;43299:238;;;:::o;43543:233::-;;43605:24;43623:5;43605:24;:::i;:::-;43596:33;;43651:66;43644:5;43641:77;43638:2;;;43721:18;;:::i;:::-;43638:2;43768:1;43761:5;43757:13;43750:20;;43586:190;;;:::o;43782:176::-;;43831:20;43849:1;43831:20;:::i;:::-;43826:25;;43865:20;43883:1;43865:20;:::i;:::-;43860:25;;43904:1;43894:2;;43909:18;;:::i;:::-;43894:2;43950:1;43947;43943:9;43938:14;;43816:142;;;;:::o;43964:180::-;44012:77;44009:1;44002:88;44109:4;44106:1;44099:15;44133:4;44130:1;44123:15;44150:180;44198:77;44195:1;44188:88;44295:4;44292:1;44285:15;44319:4;44316:1;44309:15;44336:180;44384:77;44381:1;44374:88;44481:4;44478:1;44471:15;44505:4;44502:1;44495:15;44522:180;44570:77;44567:1;44560:88;44667:4;44664:1;44657:15;44691:4;44688:1;44681:15;44708:102;;44800:2;44796:7;44791:2;44784:5;44780:14;44776:28;44766:38;;44756:54;;;:::o;44816:221::-;44956:34;44952:1;44944:6;44940:14;44933:58;45025:4;45020:2;45012:6;45008:15;45001:29;44922:115;:::o;45043:179::-;45183:31;45179:1;45171:6;45167:14;45160:55;45149:73;:::o;45228:181::-;45368:33;45364:1;45356:6;45352:14;45345:57;45334:75;:::o;45415:223::-;45555:34;45551:1;45543:6;45539:14;45532:58;45624:6;45619:2;45611:6;45607:15;45600:31;45521:117;:::o;45644:237::-;45784:34;45780:1;45772:6;45768:14;45761:58;45853:20;45848:2;45840:6;45836:15;45829:45;45750:131;:::o;45887:225::-;46027:34;46023:1;46015:6;46011:14;46004:58;46096:8;46091:2;46083:6;46079:15;46072:33;45993:119;:::o;46118:178::-;46258:30;46254:1;46246:6;46242:14;46235:54;46224:72;:::o;46302:223::-;46442:34;46438:1;46430:6;46426:14;46419:58;46511:6;46506:2;46498:6;46494:15;46487:31;46408:117;:::o;46531:175::-;46671:27;46667:1;46659:6;46655:14;46648:51;46637:69;:::o;46712:225::-;46852:34;46848:1;46840:6;46836:14;46829:58;46921:8;46916:2;46908:6;46904:15;46897:33;46818:119;:::o;46943:231::-;47083:34;47079:1;47071:6;47067:14;47060:58;47152:14;47147:2;47139:6;47135:15;47128:39;47049:125;:::o;47180:172::-;47320:24;47316:1;47308:6;47304:14;47297:48;47286:66;:::o;47358:243::-;47498:34;47494:1;47486:6;47482:14;47475:58;47567:26;47562:2;47554:6;47550:15;47543:51;47464:137;:::o;47607:229::-;47747:34;47743:1;47735:6;47731:14;47724:58;47816:12;47811:2;47803:6;47799:15;47792:37;47713:123;:::o;47842:173::-;47982:25;47978:1;47970:6;47966:14;47959:49;47948:67;:::o;48021:182::-;48161:34;48157:1;48149:6;48145:14;48138:58;48127:76;:::o;48209:166::-;48349:18;48345:1;48337:6;48333:14;48326:42;48315:60;:::o;48381:231::-;48521:34;48517:1;48509:6;48505:14;48498:58;48590:14;48585:2;48577:6;48573:15;48566:39;48487:125;:::o;48618:182::-;48758:34;48754:1;48746:6;48742:14;48735:58;48724:76;:::o;48806:228::-;48946:34;48942:1;48934:6;48930:14;48923:58;49015:11;49010:2;49002:6;48998:15;48991:36;48912:122;:::o;49040:220::-;49180:34;49176:1;49168:6;49164:14;49157:58;49249:3;49244:2;49236:6;49232:15;49225:28;49146:114;:::o;49266:220::-;49406:34;49402:1;49394:6;49390:14;49383:58;49475:3;49470:2;49462:6;49458:15;49451:28;49372:114;:::o;49492:182::-;49632:34;49628:1;49620:6;49616:14;49609:58;49598:76;:::o;49680:236::-;49820:34;49816:1;49808:6;49804:14;49797:58;49889:19;49884:2;49876:6;49872:15;49865:44;49786:130;:::o;49922:179::-;50062:31;50058:1;50050:6;50046:14;50039:55;50028:73;:::o;50107:166::-;50247:18;50243:1;50235:6;50231:14;50224:42;50213:60;:::o;50279:235::-;50419:34;50415:1;50407:6;50403:14;50396:58;50488:18;50483:2;50475:6;50471:15;50464:43;50385:129;:::o;50520:173::-;50660:25;50656:1;50648:6;50644:14;50637:49;50626:67;:::o;50699:122::-;50772:24;50790:5;50772:24;:::i;:::-;50765:5;50762:35;50752:2;;50811:1;50808;50801:12;50752:2;50742:79;:::o;50827:116::-;50897:21;50912:5;50897:21;:::i;:::-;50890:5;50887:32;50877:2;;50933:1;50930;50923:12;50877:2;50867:76;:::o;50949:120::-;51021:23;51038:5;51021:23;:::i;:::-;51014:5;51011:34;51001:2;;51059:1;51056;51049:12;51001:2;50991:78;:::o;51075:122::-;51148:24;51166:5;51148:24;:::i;:::-;51141:5;51138:35;51128:2;;51187:1;51184;51177:12;51128:2;51118:79;:::o

Swarm Source

ipfs://c47a8998073a2bfa4162b558b65eebfd121b2643d8d1bb89957aac8a54e7d60b
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.