ETH Price: $2,586.16 (-2.71%)

Token

The GOAT (GOAT)
 

Overview

Max Total Supply

11 GOAT

Holders

10

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 GOAT
0xa73827d96540e1d8cacd48017a2eb08b0e073e27
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
TheGoat

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 33 : TheGoat.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/draft-ERC721Votes.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./libraries/Base64.sol";
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import { IWETH } from './interfaces/IWETH.sol';

contract TheGoat is ERC721, ERC721Enumerable, Ownable, EIP712, ERC721Votes {
    using Counters for Counters.Counter;
    using Strings for uint256;
    Counters.Counter private _tokenIdCounter;
    uint256 public deploymentTimestamp;
    using Base64 for *;
    address private constant dev2 = 0xCC44A5Feb6Ee172dAaa31c1Fee3FC1Ce1654057F;
    address public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    event Bid (
        address indexed bidder,
        uint256 amount,
        uint256 day
    );

    struct Day {
        address winner;
        uint256 highestBid;
        bool minted;
    }

    mapping(uint256 => Day) public day;
    mapping(uint256 => uint256) private dayReward;
    mapping(uint256 => uint256) private claimed;

    enum ItemType {
        Head,
        Horn,
        Eye,
        Body
    }

    struct Item {
        string name;
        string svg;
        string json;
    }

    struct Art {
        Item[] heads;
        Item[] horns;
        Item[] bodies;
        Item[] eyes;
        uint8[3][2][4] skins;
    }

    Art private art;

    bool public artComplete = false;

    uint256 private intervalFee = 10;

    function addItems(
        ItemType _itemType,
        string[] memory _names,
        string[] memory _svgs,
        string[] memory _jsons
    ) public onlyOwner {
        require(
            _names.length == _svgs.length && _names.length == _jsons.length,
            "Array lengths must match"
        );

        require(!artComplete, "Art is already complete");

        for (uint256 i = 0; i < _names.length; i++) {
            if (_itemType == ItemType.Head) {
                art.heads.push(Item(_names[i], _svgs[i], _jsons[i]));
            } else if (_itemType == ItemType.Horn) {
                art.horns.push(Item(_names[i], _svgs[i], _jsons[i]));
            } else if (_itemType == ItemType.Eye) {
                art.eyes.push(Item(_names[i], _svgs[i], _jsons[i]));
            } else if (_itemType == ItemType.Body) {
                art.bodies.push(Item(_names[i], _svgs[i], _jsons[i]));
            }
        }
    }

    function lockArt() public onlyOwner {
        require(!artComplete, "Art is already complete");
        artComplete = true;
    }

    constructor() ERC721("The GOAT", "GOAT") EIP712("TheGoat", "1") {
        deploymentTimestamp = block.timestamp;
        art.skins = [
            [[102, 72, 33], [135, 103, 46]],
            [[98, 98, 98], [160, 160, 160]],
            [[119, 39, 23], [162, 70, 28]],
            [[176, 173, 134], [205, 202, 166]]
        ];
        safeMint(owner(), 0);
        safeMint(0x0e802Eef59d855375e4826123a4145B829Bc3F83, 1);
        safeMint(0x184Fd7ACe17722dA2fFD9DC1F951DA8283253cdf, 2);
        safeMint(0xf728Ce79C82BB99335e0A781CAc0254B6a9AEb37, 3);
        safeMint(0x5D2A610dfCFF2B38e82DF7F2C3C100CF6332527D, 4);
        safeMint(0xa73827D96540E1d8CAcd48017a2eb08B0e073e27, 5);
        safeMint(0xc2B35534e47cdF3D787e01630129631d8270abFb, 6);
    }

    function getDayId() public view returns (uint256) {
        return (block.timestamp - deploymentTimestamp) / 1 days + 1;
    }

    function getGoatsSinceDeployment() public view returns (uint256) {
        return 6 + getDayId() + getDayId() / intervalFee;
    }

    function bid() public payable {
        require(
            msg.value > 0,
            "You must send some ether to participate in the auction."
        );
        uint256 currentDay = getGoatsSinceDeployment();
        require(msg.value > day[currentDay].highestBid + 1000000 gwei, "Your bid is too low.");
        require(
            day[currentDay].winner != msg.sender,
            "You are already the winner."
        );

        address payable lastBidder = payable(day[currentDay].winner);
        uint256 lastBid = day[currentDay].highestBid;
        
        day[currentDay].highestBid = msg.value;
        day[currentDay].winner = msg.sender;
        calculateRewards(currentDay);
        emit Bid(msg.sender, msg.value, currentDay);
        if (lastBidder != address(0)) {
            _safeTransferETHWithFallback(lastBidder, lastBid);
        }
    }

    function mint(uint256 goatId) public {
        require(day[goatId].winner == msg.sender, "You are not the winner.");
        require(day[goatId].minted == false, "You already minted your NFT.");
        require(goatId % intervalFee != 0, "It's Sunday.");
        require(goatId < getGoatsSinceDeployment(), "Day not reached yet.");
        safeMint(msg.sender, goatId);
    }

    function mintSunday(uint256 goatId) public {
        require(goatId % intervalFee == 0, "It's not Sunday.");
        require(day[goatId].minted == false, "You already minted your NFT.");
        require(goatId < getGoatsSinceDeployment(), "Day not reached yet.");
        if (goatId % 20 == 0) {
            safeMint(owner(), goatId);
        } else {
            safeMint(dev2, goatId);
        }
    }

    function mintUnminted(uint256 goatId) public {
        require(day[goatId].minted == false, "You already minted your NFT.");
        require(
            goatId + intervalFee < getGoatsSinceDeployment(),
            "Day not reached yet."
        );

        safeMint(owner(), goatId);
    }

    function safeMint(address to, uint256 id) internal {
        day[id].minted = true;
        claimed[id] += dayReward[id];
        _safeMint(to, id);
    }

    function dna(uint256 _tokenId) internal pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(_tokenId, "TheGoat")));
    }

    function claim(uint256 _tokenId) public {
        require(_exists(_tokenId));
        require(_msgSender() == ownerOf(_tokenId));
        require(_tokenId < getGoatsSinceDeployment());

        uint256 amount = claimable(_tokenId);

        if (amount > 0) {
            claimed[_tokenId] += amount;
            payable(_msgSender()).transfer(amount);
        }
    }

    function claimMultiple(uint256[] calldata ownedNfts) public {
        for (uint256 i = 0; i < ownedNfts.length; ) {
            claim(ownedNfts[i]);
            unchecked {
                i++;
            }
        }
    }

    function claimable(uint256 tokenId) public view returns (uint256) {
        uint256 yesterday = getGoatsSinceDeployment() - 1;
        while (dayReward[yesterday] == 0 && yesterday > 0) {
            yesterday--;
        }
        return dayReward[yesterday] - claimed[tokenId];
    }

    function calculateRewards(uint256 _day) public {
        require(_day <= getGoatsSinceDeployment());
        require(_day > 0);
        if (dayReward[_day - 1] == 0 && _day > 1) {
            calculateRewards(_day - 1);
        }
        dayReward[_day] = dayReward[_day - 1] + day[_day].highestBid / _day;
    }

    function getWinningDays(
        address user
    ) public view returns (uint256[] memory) {
        uint256 goatsSinceDeployment = getGoatsSinceDeployment();
        uint256[] memory winningDays = new uint256[](goatsSinceDeployment);
        uint256 count = 0;

        for (uint256 i = 0; i < goatsSinceDeployment; i++) {
            if (day[i].winner == user && day[i].minted == false) {
                winningDays[count] = i;
                count++;
            }
        }
        uint256[] memory result = new uint256[](count);
        for (uint256 i = 0; i < count; i++) {
            result[i] = winningDays[i];
        }

        return result;
    }

    // image

    function imageData(uint256 _tokenId) public view returns (string memory) {
        require(_tokenId <= getGoatsSinceDeployment(), "Day not reached yet.");

        uint8[4] memory tdna = splitNumber(dna(_tokenId));

        require(tdna[0] < art.heads.length, "Invalid index for art.heads");
        require(tdna[1] < art.horns.length, "Invalid index for art.horns");
        require(tdna[2] < art.bodies.length, "Invalid index for art.bodies");
        require(tdna[3] < art.eyes.length, "Invalid index for art.eyes");
        uint8[3][9] memory colors = magicColors(_tokenId);

        return
            string(
                abi.encodePacked(
                    "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -0.5 28 28' shape-rendering='crispEdges'><style> .c1{stroke:",
                    rgbToString(colors[0]),
                    ";} .c2{stroke:",
                    rgbToString(colors[1]),
                    ";} .c3{stroke:",
                    rgbToString(colors[2]),
                    ";} .c5{stroke:",
                    rgbToString(colors[3]),
                    ";} .c6{stroke:",
                    rgbToString(colors[4]),
                    ";} .d2{stroke:",
                    rgbToString(colors[5]),
                    ";} .d3{stroke:",
                    rgbToString(colors[6]),
                    ";} .d4{stroke:",
                    rgbToString(colors[7]),
                    ";} .d6{stroke:",
                    rgbToString(colors[8]),
                    ";} .s1{stroke:",
                    rgbToString(art.skins[tdna[0]][0]),
                    ";} .s2{stroke:",
                    rgbToString(art.skins[tdna[0]][1]),
                    ';} </style><path class="c1" d="M0 0h28M0 1h28M0 2h28M0 3h28M0 4h28M0 5h28M0 6h28M0 7h28M0 8h28M0 9h28M0 10h28M0 11h28M0 12h28M0 13h28M0 14h28M0 15h28M0 16h28M0 17h28M0 18h28M0 19h28M0 20h28M0 21h28M0 22h28M0 23h28M0 24h28M0 25h28M0 26h28M0 27h28"/>',
                    art.bodies[tdna[2]].svg,
                    art.heads[tdna[0]].svg,
                    art.horns[tdna[1]].svg,
                    art.eyes[tdna[3]].svg,
                    "</svg>"
                )
            );
    }

    function splitNumber(
        uint256 _number
    ) internal view returns (uint8[4] memory) {
        uint8[4] memory numbers;
        numbers[0] = uint8(_number % art.heads.length); // head
        _number /= art.heads.length;
        numbers[1] = uint8(_number % art.horns.length); // horns
        _number /= art.horns.length;
        numbers[2] = uint8(_number % art.bodies.length); // body
        _number /= art.bodies.length;
        numbers[3] = uint8(_number % art.eyes.length); // eyes

        return numbers;
    }

    function tokenURI(
        uint256 _tokenId
    ) public view virtual override returns (string memory) {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        uint8[4] memory tdna = splitNumber(dna(_tokenId));
        bytes memory baseURI = (
            abi.encodePacked(
                '{ "attributes": [',
                art.heads[tdna[0]].json,
                ",",
                art.horns[tdna[1]].json,
                ",",
                art.bodies[tdna[2]].json,
                ",",
                art.eyes[tdna[3]].json,
                ",",
                '{"trait_type": "Color", "value": "',
                rgbToString(getRandomColor(_tokenId)),
                '"}',
                "],",
                '"description": "Created by thegoat.wtf","external_url": "https://thegoat.wtf","image": "data:image/svg+xml;base64,',
                bytes(imageData(_tokenId)).encode(),
                '","name": "The Goat #',
                _tokenId.toString(),
                '"}'
            )
        );

        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    baseURI.encode()
                )
            );
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 batchSize
    ) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 batchSize
    ) internal override(ERC721, ERC721Votes) {
        super._afterTokenTransfer(from, to, tokenId, batchSize);
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function magicColors(
        uint256 _tokenId
    ) public pure returns (uint8[3][9] memory) {
        uint8[3] memory c = getRandomColor(_tokenId);
        uint8[3] memory d = getCColor(c);
        return (
            [
                adjustColor(c, 210, 253),
                adjustColor(c, 128, 240),
                adjustColor(c, 64, 200),
                adjustColor(c, 64, 128),
                adjustColor(c, 20, 64),
                adjustColor(d, 128, 240),
                adjustColor(d, 64, 200),
                adjustColor(d, 64, 128),
                adjustColor(d, 20, 64)
            ]
        );
    }

    function getRandomColor(uint id) internal pure returns (uint8[3] memory) {
        return [
            getRandomNumber(id),
            getRandomNumber(id + 1337),
            getRandomNumber(id + 13371337)
        ];
    }

    function getRandomNumber(uint256 nonce) internal pure returns (uint8) {
        return uint8(uint256(keccak256(abi.encodePacked(nonce))) % 256);
    }

    function getCColor(
        uint8[3] memory color
    ) internal pure returns (uint8[3] memory) {
        uint8[3] memory complementary;

        complementary[0] = 255 - color[0];
        complementary[1] = 255 - color[1];
        complementary[2] = 255 - color[2];

        return complementary;
    }

    function adjustColor(
        uint8[3] memory input,
        uint8 minOutput,
        uint8 maxOutput
    ) internal pure returns (uint8[3] memory) {
        uint256 inputRange = 255;
        uint256 outputRange = uint256(maxOutput) - uint256(minOutput);

        uint8[3] memory adjustedColor;
        adjustedColor[0] = uint8(
            (uint256(input[0]) * outputRange) / inputRange + uint256(minOutput)
        );
        adjustedColor[1] = uint8(
            (uint256(input[1]) * outputRange) / inputRange + uint256(minOutput)
        );
        adjustedColor[2] = uint8(
            (uint256(input[2]) * outputRange) / inputRange + uint256(minOutput)
        );

        return adjustedColor;
    }

    function rgbToString(
        uint8[3] memory color
    ) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    "rgb(",
                    Strings.toString(color[0]),
                    ",",
                    Strings.toString(color[1]),
                    ",",
                    Strings.toString(color[2]),
                    ")"
                )
            );
    }

    function _safeTransferETHWithFallback(address to, uint256 amount) internal {
        if (!_safeTransferETH(to, amount)) {
            IWETH(weth).deposit{value: amount}();
            IERC20(weth).transfer(to, amount);
        }
    }

    /**
     * @notice Transfer ETH and return the success status.
     * @dev This function only forwards 30,000 gas to the callee.
     */
    function _safeTransferETH(
        address to,
        uint256 value
    ) internal returns (bool) {
        (bool success, ) = to.call{value: value, gas: 30_000}(new bytes(0));
        return success;
    }
}

File 2 of 33 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/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() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(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");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 33 : IVotes.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     */
    function getPastVotes(address account, uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}

File 4 of 33 : Votes.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/Votes.sol)
pragma solidity ^0.8.0;

import "../../interfaces/IERC5805.sol";
import "../../utils/Context.sol";
import "../../utils/Counters.sol";
import "../../utils/Checkpoints.sol";
import "../../utils/cryptography/EIP712.sol";

/**
 * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be
 * transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of
 * "representative" that will pool delegated voting units from different accounts and can then use it to vote in
 * decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to
 * delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative.
 *
 * This contract is often combined with a token contract such that voting units correspond to token units. For an
 * example, see {ERC721Votes}.
 *
 * The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed
 * at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the
 * cost of this history tracking optional.
 *
 * When using this module the derived contract must implement {_getVotingUnits} (for example, make it return
 * {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the
 * previous example, it would be included in {ERC721-_beforeTokenTransfer}).
 *
 * _Available since v4.5._
 */
abstract contract Votes is Context, EIP712, IERC5805 {
    using Checkpoints for Checkpoints.Trace224;
    using Counters for Counters.Counter;

    bytes32 private constant _DELEGATION_TYPEHASH =
        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    mapping(address => address) private _delegation;

    /// @custom:oz-retyped-from mapping(address => Checkpoints.History)
    mapping(address => Checkpoints.Trace224) private _delegateCheckpoints;

    /// @custom:oz-retyped-from Checkpoints.History
    Checkpoints.Trace224 private _totalCheckpoints;

    mapping(address => Counters.Counter) private _nonces;

    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based
     * checkpoints (and voting), in which case {CLOCK_MODE} should be overridden as well to match.
     */
    function clock() public view virtual override returns (uint48) {
        return SafeCast.toUint48(block.number);
    }

    /**
     * @dev Machine-readable description of the clock as specified in EIP-6372.
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() public view virtual override returns (string memory) {
        // Check that the clock was not modified
        require(clock() == block.number, "Votes: broken clock mode");
        return "mode=blocknumber&from=default";
    }

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) public view virtual override returns (uint256) {
        return _delegateCheckpoints[account].latest();
    }

    /**
     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     *
     * Requirements:
     *
     * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
     */
    function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) {
        require(timepoint < clock(), "Votes: future lookup");
        return _delegateCheckpoints[account].upperLookupRecent(SafeCast.toUint32(timepoint));
    }

    /**
     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     *
     * Requirements:
     *
     * - `timepoint` must be in the past. If operating using block numbers, the block must be already mined.
     */
    function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) {
        require(timepoint < clock(), "Votes: future lookup");
        return _totalCheckpoints.upperLookupRecent(SafeCast.toUint32(timepoint));
    }

    /**
     * @dev Returns the current total supply of votes.
     */
    function _getTotalSupply() internal view virtual returns (uint256) {
        return _totalCheckpoints.latest();
    }

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) public view virtual override returns (address) {
        return _delegation[account];
    }

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) public virtual override {
        address account = _msgSender();
        _delegate(account, delegatee);
    }

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= expiry, "Votes: signature expired");
        address signer = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
            v,
            r,
            s
        );
        require(nonce == _useNonce(signer), "Votes: invalid nonce");
        _delegate(signer, delegatee);
    }

    /**
     * @dev Delegate all of `account`'s voting units to `delegatee`.
     *
     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
     */
    function _delegate(address account, address delegatee) internal virtual {
        address oldDelegate = delegates(account);
        _delegation[account] = delegatee;

        emit DelegateChanged(account, oldDelegate, delegatee);
        _moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account));
    }

    /**
     * @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to`
     * should be zero. Total supply of voting units will be adjusted with mints and burns.
     */
    function _transferVotingUnits(address from, address to, uint256 amount) internal virtual {
        if (from == address(0)) {
            _push(_totalCheckpoints, _add, SafeCast.toUint224(amount));
        }
        if (to == address(0)) {
            _push(_totalCheckpoints, _subtract, SafeCast.toUint224(amount));
        }
        _moveDelegateVotes(delegates(from), delegates(to), amount);
    }

    /**
     * @dev Moves delegated votes from one delegate to another.
     */
    function _moveDelegateVotes(address from, address to, uint256 amount) private {
        if (from != to && amount > 0) {
            if (from != address(0)) {
                (uint256 oldValue, uint256 newValue) = _push(
                    _delegateCheckpoints[from],
                    _subtract,
                    SafeCast.toUint224(amount)
                );
                emit DelegateVotesChanged(from, oldValue, newValue);
            }
            if (to != address(0)) {
                (uint256 oldValue, uint256 newValue) = _push(
                    _delegateCheckpoints[to],
                    _add,
                    SafeCast.toUint224(amount)
                );
                emit DelegateVotesChanged(to, oldValue, newValue);
            }
        }
    }

    function _push(
        Checkpoints.Trace224 storage store,
        function(uint224, uint224) view returns (uint224) op,
        uint224 delta
    ) private returns (uint224, uint224) {
        return store.push(SafeCast.toUint32(clock()), op(store.latest(), delta));
    }

    function _add(uint224 a, uint224 b) private pure returns (uint224) {
        return a + b;
    }

    function _subtract(uint224 a, uint224 b) private pure returns (uint224) {
        return a - b;
    }

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }

    /**
     * @dev Returns an address nonce.
     */
    function nonces(address owner) public view virtual returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev Returns the contract's {EIP712} domain separator.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev Must return the voting units held by an account.
     */
    function _getVotingUnits(address) internal view virtual returns (uint256);
}

File 5 of 33 : IERC5267.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.0;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

File 6 of 33 : IERC5805.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol)

pragma solidity ^0.8.0;

import "../governance/utils/IVotes.sol";
import "./IERC6372.sol";

interface IERC5805 is IERC6372, IVotes {}

File 7 of 33 : IERC6372.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol)

pragma solidity ^0.8.0;

interface IERC6372 {
    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
     */
    function clock() external view returns (uint48);

    /**
     * @dev Description of the clock
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() external view returns (string memory);
}

File 8 of 33 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev 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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}

File 9 of 33 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

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

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

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual 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: caller is not token owner or 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: caller is not token owner or 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 the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @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 virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `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, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

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

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

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

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @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(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @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()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
     * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
     * that `ownerOf(tokenId)` is `a`.
     */
    // solhint-disable-next-line func-name-mixedcase
    function __unsafe_increaseBalance(address account, uint256 amount) internal {
        _balances[account] += amount;
    }
}

File 10 of 33 : draft-ERC721Votes.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/draft-ERC721Votes.sol)

pragma solidity ^0.8.0;

// ERC721Votes was marked as draft due to the EIP-712 dependency.
// EIP-712 is Final as of 2022-08-11. This file is deprecated.

import "./ERC721Votes.sol";

File 11 of 33 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

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

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

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

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

        if (batchSize > 1) {
            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
            revert("ERC721Enumerable: consecutive transfers not supported");
        }

        uint256 tokenId = firstTokenId;

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

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

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

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

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

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

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

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

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

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

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

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

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

File 12 of 33 : ERC721Votes.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/extensions/ERC721Votes.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../governance/utils/Votes.sol";

/**
 * @dev Extension of ERC721 to support voting and delegation as implemented by {Votes}, where each individual NFT counts
 * as 1 vote unit.
 *
 * Tokens do not count as votes until they are delegated, because votes must be tracked which incurs an additional cost
 * on every transfer. Token holders can either delegate to a trusted representative who will decide how to make use of
 * the votes in governance decisions, or they can delegate to themselves to be their own representative.
 *
 * _Available since v4.5._
 */
abstract contract ERC721Votes is ERC721, Votes {
    /**
     * @dev See {ERC721-_afterTokenTransfer}. Adjusts votes when tokens are transferred.
     *
     * Emits a {IVotes-DelegateVotesChanged} event.
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        _transferVotingUnits(from, to, batchSize);
        super._afterTokenTransfer(from, to, firstTokenId, batchSize);
    }

    /**
     * @dev Returns the balance of `account`.
     *
     * WARNING: Overriding this function will likely result in incorrect vote tracking.
     */
    function _getVotingUnits(address account) internal view virtual override returns (uint256) {
        return balanceOf(account);
    }
}

File 13 of 33 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

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);

    /**
     * @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 14 of 33 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

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 15 of 33 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/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`.
     *
     * 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;

    /**
     * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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 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 the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

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

File 16 of 33 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

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 `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 17 of 33 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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");

        (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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 18 of 33 : Checkpoints.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Checkpoints.sol)
// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SafeCast.sol";

/**
 * @dev This library defines the `History` struct, for checkpointing values as they change at different points in
 * time, and later looking up past values by block number. See {Votes} as an example.
 *
 * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
 * checkpoint for the current transaction block using the {push} function.
 *
 * _Available since v4.5._
 */
library Checkpoints {
    struct History {
        Checkpoint[] _checkpoints;
    }

    struct Checkpoint {
        uint32 _blockNumber;
        uint224 _value;
    }

    /**
     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
     * before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
     * block, the requested block number must be in the past, excluding the current block.
     */
    function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
        require(blockNumber < block.number, "Checkpoints: block not yet mined");
        uint32 key = SafeCast.toUint32(blockNumber);

        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
     * before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
     * checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
     * checkpoints.
     */
    function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
        require(blockNumber < block.number, "Checkpoints: block not yet mined");
        uint32 key = SafeCast.toUint32(blockNumber);

        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
     *
     * Returns previous value and new value.
     */
    function push(History storage self, uint256 value) internal returns (uint256, uint256) {
        return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
    }

    /**
     * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
     * be set to `op(latest, delta)`.
     *
     * Returns previous value and new value.
     */
    function push(
        History storage self,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) internal returns (uint256, uint256) {
        return push(self, op(latest(self), delta));
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(History storage self) internal view returns (uint224) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(
        History storage self
    ) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._blockNumber, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(History storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._blockNumber <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._blockNumber == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint({_blockNumber: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint({_blockNumber: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._blockNumber > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._blockNumber < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }

    struct Trace224 {
        Checkpoint224[] _checkpoints;
    }

    struct Checkpoint224 {
        uint32 _key;
        uint224 _value;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.
     *
     * Returns previous value and new value.
     */
    function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {
        return _insert(self._checkpoints, key, value);
    }

    /**
     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
     */
    function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
    }

    /**
     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
     */
    function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
     *
     * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
     */
    function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {
        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(Trace224 storage self) internal view returns (uint224) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._key, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(Trace224 storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint224 memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._key <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._key == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint224({_key: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint224({_key: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint224[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint224[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(
        Checkpoint224[] storage self,
        uint256 pos
    ) private pure returns (Checkpoint224 storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }

    struct Trace160 {
        Checkpoint160[] _checkpoints;
    }

    struct Checkpoint160 {
        uint96 _key;
        uint160 _value;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.
     *
     * Returns previous value and new value.
     */
    function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {
        return _insert(self._checkpoints, key, value);
    }

    /**
     * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
     */
    function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
        return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
    }

    /**
     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
     */
    function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;
        uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
     *
     * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
     */
    function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {
        uint256 len = self._checkpoints.length;

        uint256 low = 0;
        uint256 high = len;

        if (len > 5) {
            uint256 mid = len - Math.sqrt(len);
            if (key < _unsafeAccess(self._checkpoints, mid)._key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);

        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
     */
    function latest(Trace160 storage self) internal view returns (uint160) {
        uint256 pos = self._checkpoints.length;
        return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
    }

    /**
     * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
     * in the most recent checkpoint.
     */
    function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {
        uint256 pos = self._checkpoints.length;
        if (pos == 0) {
            return (false, 0, 0);
        } else {
            Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
            return (true, ckpt._key, ckpt._value);
        }
    }

    /**
     * @dev Returns the number of checkpoint.
     */
    function length(Trace160 storage self) internal view returns (uint256) {
        return self._checkpoints.length;
    }

    /**
     * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
     * or by updating the last one.
     */
    function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) {
        uint256 pos = self.length;

        if (pos > 0) {
            // Copying to memory is important here.
            Checkpoint160 memory last = _unsafeAccess(self, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require(last._key <= key, "Checkpoint: decreasing keys");

            // Update or push new checkpoint
            if (last._key == key) {
                _unsafeAccess(self, pos - 1)._value = value;
            } else {
                self.push(Checkpoint160({_key: key, _value: value}));
            }
            return (last._value, value);
        } else {
            self.push(Checkpoint160({_key: key, _value: value}));
            return (0, value);
        }
    }

    /**
     * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _upperBinaryLookup(
        Checkpoint160[] storage self,
        uint96 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
     * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
     *
     * WARNING: `high` should not be greater than the array's length.
     */
    function _lowerBinaryLookup(
        Checkpoint160[] storage self,
        uint96 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_unsafeAccess(self, mid)._key < key) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return high;
    }

    /**
     * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
     */
    function _unsafeAccess(
        Checkpoint160[] storage self,
        uint256 pos
    ) private pure returns (Checkpoint160 storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }
}

File 19 of 33 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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) {
        return msg.data;
    }
}

File 20 of 33 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

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

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

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 21 of 33 : draft-EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

// EIP-712 is Final as of 2022-08-11. This file is deprecated.

import "./EIP712.sol";

File 22 of 33 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

File 23 of 33 : EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.8;

import "./ECDSA.sol";
import "../ShortStrings.sol";
import "../../interfaces/IERC5267.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * _Available since v3.4._
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant _TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {EIP-5267}.
     *
     * _Available since v4.9._
     */
    function eip712Domain()
        public
        view
        virtual
        override
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _name.toStringWithFallback(_nameFallback),
            _version.toStringWithFallback(_versionFallback),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }
}

File 24 of 33 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

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 25 of 33 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

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 26 of 33 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 27 of 33 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 28 of 33 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 29 of 33 : ShortStrings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.8;

import "./StorageSlot.sol";

// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(_FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

File 30 of 33 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 31 of 33 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 32 of 33 : IWETH.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.6;

interface IWETH {
    function deposit() external payable;

    function withdraw(uint256 wad) external;

    function transfer(address to, uint256 value) external returns (bool);
}

File 33 of 33 : Base64.sol
// SPDX-License-Identifier: MIT

/// @title Base64
/// @author Brecht Devos - <[email protected]>
/// @notice Provides a function for encoding some bytes in base64
pragma solidity ^0.8.18;
library Base64 {
    string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';
        
        // load the table into memory
        string memory table = TABLE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)
            
            // prepare the lookup table
            let tablePtr := add(table, 1)
            
            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))
            
            // result ptr, jump over length
            let resultPtr := add(result, 32)
            
            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
            {
               dataPtr := add(dataPtr, 3)
               
               // read 3 bytes
               let input := mload(dataPtr)
               
               // write 4 characters
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(        input,  0x3F)))))
               resultPtr := add(resultPtr, 1)
            }
            
            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
        }
        
        return result;
    }
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"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":true,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"day","type":"uint256"}],"name":"Bid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","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":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum TheGoat.ItemType","name":"_itemType","type":"uint8"},{"internalType":"string[]","name":"_names","type":"string[]"},{"internalType":"string[]","name":"_svgs","type":"string[]"},{"internalType":"string[]","name":"_jsons","type":"string[]"}],"name":"addItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"artComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_day","type":"uint256"}],"name":"calculateRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ownedNfts","type":"uint256[]"}],"name":"claimMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"day","outputs":[{"internalType":"address","name":"winner","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"bool","name":"minted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deploymentTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDayId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGoatsSinceDeployment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getWinningDays","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"imageData","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[],"name":"lockArt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"magicColors","outputs":[{"internalType":"uint8[3][9]","name":"","type":"uint8[3][9]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"goatId","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"goatId","type":"uint256"}],"name":"mintSunday","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"goatId","type":"uint256"}],"name":"mintUnminted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_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":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60406101608152346200026d57620000406200001a6200033b565b6200002462000360565b6200002e6200037f565b9062000039620003a5565b926200048c565b601380546001600160a01b03191673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21790556200007660ff1960235416602355565b62000081600a602455565b6200008b42601255565b620001ca62000099620002fb565b620000a3620002ea565b620000ad6200031b565b6066815290602091620000c283820160489052565b6021818701528152620000d46200031b565b60878152606781840152602e81870152828201528252620000f4620002ea565b620000fe6200031b565b6062815260628184015260628187015281526200011a6200031b565b60a0815260a08184015260a08187015282820152818301526200013c620002ea565b620001466200031b565b607781526027818401526017818701528152620001626200031b565b60a28152604681840152601c81870152828201528483015262000184620002ea565b906200018f6200031b565b60b0815260ad818301526086818701528252620001ab6200031b565b60cd81529060ca8282015260a6828701528201526060820152620003f6565b600a54620001e1906001600160a01b031662000b89565b620001eb62000d6f565b620001f562000f04565b620001ff6200109b565b6200020962001223565b62000213620013b5565b6200021d6200153d565b51615b78908162002aa68239608051816130c2015260a0518161317d015260c0518161308c015260e051816131110152610100518161313701526101205181611179015261014051816111a50152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b03821117620002a457604052565b62000272565b602081019081106001600160401b03821117620002a457604052565b601f909101601f19168101906001600160401b03821190821017620002a457604052565b60405190620002f98262000288565b565b60405190608082016001600160401b03811183821017620002a457604052565b60405190606082016001600160401b03811183821017620002a457604052565b604051906200034a8262000288565b6007825266151a1951dbd85d60ca1b6020830152565b604051906200036f8262000288565b60018252603160f81b6020830152565b604051906200038e8262000288565b6008825267151a194811d3d05560c21b6020830152565b60405190620003b48262000288565b600482526311d3d05560e21b6020830152565b634e487b7160e01b600052601160045260246000fd5b818110620003e9575050565b60008155600101620003dd565b601b906000905b600482106200040b57505050565b8051836000915b6002831062000432575050506002602060019201930191019091620003fd565b919492829491945191600090815b600390818410156200046f5760019160209160ff86818a5116931b92831b921b19161795019201919362000440565b885550949694959194600190810194920192505060200162000412565b82519193909290916001600160401b038111620002a457600091620004bd82620004b78554620005e5565b62000622565b602090601f83116001146200055857620004f7949392918391836200054c575b50508160011b916000199060031b1c191617905562000725565b620005023362000816565b6200050d816200085f565b610120526200051c8262000972565b610140526020815191012060e05260208151910120610100524660a0526200054362000b1d565b6080523060c052565b015190503880620004dd565b600080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639190601f198416855b818110620005cc5750916001939185620004f79897969410620005b2575b505050811b01905562000725565b015160001960f88460031b161c19169055388080620005a4565b9293602060018192878601518155019501930162000586565b90600182811c9216801562000617575b60208310146200060157565b634e487b7160e01b600052602260045260246000fd5b91607f1691620005f5565b90601f821162000630575050565b620002f991600080526020600020906020601f840160051c8301931062000660575b601f0160051c0190620003dd565b909150819062000652565b90601f821162000679575050565b620002f99160016000526020600020906020601f840160051c830193106200066057601f0160051c0190620003dd565b90601f8211620006b7575050565b620002f991600b6000526020600020906020601f840160051c830193106200066057601f0160051c0190620003dd565b90601f8211620006f5575050565b620002f991600c6000526020600020906020601f840160051c830193106200066057601f0160051c0190620003dd565b80519091906001600160401b038111620002a45760019062000753816200074d8454620005e5565b6200066b565b602080601f83116001146200079157508192939460009262000785575b5050600019600383901b1c191690821b179055565b01519050388062000770565b6001600052601f198316959091907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000905b888210620007fe5750508385969710620007e4575b505050811b019055565b015160001960f88460031b161c19169055388080620007da565b808785968294968601518155019501930190620007c5565b600a80546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b908151602080821060001462000880575050906200087d9062000ac4565b90565b6001600160401b038211620002a457620008a782620008a1600b54620005e5565b620006a9565b80601f8311600114620008e75750819293600092620008db575b50508160011b916000199060031b1c191617600b5560ff90565b015190503880620008c1565b600b600052601f198316949091907f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9926000905b878210620009595750508360019596106200093f575b505050811b01600b5560ff90565b015160001960f88460031b161c1916905538808062000931565b806001859682949686015181550195019301906200091b565b908151602080821060001462000990575050906200087d9062000ac4565b6001600160401b038211620002a457620009b782620009b1600c54620005e5565b620006e7565b80601f8311600114620009f75750819293600092620009eb575b50508160011b916000199060031b1c191617600c5560ff90565b015190503880620009d1565b600c600052601f198316949091907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7926000905b87821062000a6957505083600195961062000a4f575b505050811b01600c5560ff90565b015160001960f88460031b161c1916905538808062000a41565b8060018596829496860151815501950193019062000a2b565b919082519283825260005b84811062000aaf575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520162000a8d565b601f81511162000af257602081519101516020821062000ae2571790565b6000198260200360031b1b161790565b60405163305a27a960e01b81526020600482015290819062000b1990602483019062000a82565b0390fd5b60e051610100516040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815260c0810181811060018060401b03821117620002a45760405251902090565b60008080527f4f26c3876aa9f4b92579780beea1161a61f87ebf1ec6ee865b299e447ecba99e805460ff191660011790557fa31547ce6245cdb9ecea19cf8c7eb9f5974025bb4075011409251ae855b30aed5460166020527f0263c2b778d062355049effc2dece97bc6547ff8a88a3258daa512061c2153dd805492939291820191821062000d69575560405162000c2181620002aa565b8281526001600160a01b03821691821562000d25576000805260026020526000805160206200869e83398151915254620002f99462000d1f94909162000c77906001600160a01b0316156200171c565b6200171c565b62000c828362001bc0565b6000805260026020526000805160206200869e8339815191525462000cb1906001600160a01b0316156200171c565b6001600160a01b0383166000818152600360209081526040822080546001019055908052600290526000805160206200869e83398151915280546001600160a01b031916909117905581600080516020620086de8339815191528180a462000d19816200247c565b6200192c565b620016c5565b606460405162461bcd60e51b815260206004820152602060248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152fd5b620003c7565b600160008181527fb6c61a840592cc84133e4b25bd509abf4659307c57b160799b38490a5aa48f2e805460ff1916831790557f27739e4bb5e6f8b5e4b57a047dca8767cc9b982a011081e086cbb0dfa9de818d5460166020527f4c4dc693d7db52f85fe052106f4b4b920e78e8ef37dee82878a60ab8585faf4980549293918301926040929190841062000d6957620002f99462000d1f94600080516020620086fe833981519152925562000e7062000c7185519562000e2f87620002aa565b8387528584526002602052808420546001600160a01b03919062000e56908316156200171c565b62000e6062001c50565b8685526002602052842054161590565b7fdfa8dbdf6d3211bdac983d8cfb904c8192c5e5d2e815ae8862bc60f11fd9399f805484019055600160005260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e080546001600160a01b031916600080516020620086fe833981519152179055600080516020620086de8339815191528180a462000efe6200203c565b62001a2a565b600260008181527fa1930aa930426c54c34daad2b9ada7c5d0ef0c96078a3c5bb79f6fa6602c4a7c805460ff191660011790557f07d4ff730d9753101d832555708a37d38c2c45fce8cacaefc99f06074e93fe0b5460166020527fcaff291fe014adc6b72a172705750b4cabe8f8667664d2924a166caab288564880549293918301926040929190841062000d6957620002f99462000d1f946000805160206200867e83398151915292556200100662000c7185519562000fc587620002aa565b8387528584526020869052808420546001600160a01b03919062000fec908316156200171c565b62000ff662001ccf565b8685526020879052842054161590565b7f41dfb724cd6ce5ea0d6c2d4f5faea8d759b3e4d09ec4dc657bfb2fd78b11ed1080546001019055600260008190526020527f679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28c80546001600160a01b0319166000805160206200867e833981519152179055600080516020620086de8339815191528180a46200109562002189565b62001a85565b600360009081527f63d87a887046e0430be80fdeb014107d7198c879cbf2cddf39a6df195c86cb3a805460ff191660011790557fb3a65e8276bd33b3e4f7d6081ebd9899187264822358758dca2e2bc37b2a9c275460166020527ff06d282f967055cb1eee17e04aa005b9682a620f4bbcfaee55ba78607a3d87ae805490929160409190810190811062000d69576000805160206200873e83398151915262000d1f93600392620002f996556200118e62000c718551956200115d87620002aa565b8387528584526002602052808420546001600160a01b03919062001184908316156200171c565b62000e6062001d4e565b7f499842051fc28b6f1cf7e6b91d8537e7602c1bbc5f521c28365b3ad6cddd95eb80546001019055600360005260026020527f88601476d11616a71c5be67555bd1dff4b1cbf21533d2669b768b61518cfe1c380546001600160a01b0319166000805160206200873e833981519152179055600080516020620086de8339815191528180a46200121d6200221f565b62001ac3565b600460009081527f52102136546d97ed3f65ec1070a32935d3048ea12f310d29c378dc9d6555c0d8805460ff191660011790557f8191f4eb6b8bafbfe9a5389c8d07d7f5fd81137a7ee653fc4358269845ee1d2e5460166020527fec061709de2491458f4c981032059d7d19b0e55f45018bac6b3e660bdc959a59805490929160409190810190811062000d6957735d2a610dfcff2b38e82df7f2c3c100cf6332527d62000d1f93600492620002f996556200131b62000c71855195620012ea87620002aa565b8387528584526002602052808420546001600160a01b03919062001311908316156200171c565b62000e6062001dcd565b7fe9fe1ed8c835c5d67182e134314949756a777744f22cc0cc5fe1896a5d0b806d80546001019055600460005260026020527fee60d0579bcffd98e668647d59fec1ff86a7fb340ce572e844f234ae73a6918f80546001600160a01b031916735d2a610dfcff2b38e82df7f2c3c100cf6332527d179055600080516020620086de8339815191528180a4620013af620022b5565b62001b01565b600560009081527f116126bec5aaa49b347e966c49378cf0c441de9121e306ea3d824584a9615aa4805460ff191660011790557fbab719002e4be320868650dc7456e9a1d245e4d5dd64765588e2f21529d871d35460166020527f5696377e725b42a372ecc45f0fbdab5e9555865aef54619ad9381892f667bbf0805490929160409190810190811062000d69576000805160206200865e83398151915262000d1f93600592620002f99655620014a862000c718551956200147787620002aa565b8387528584526002602052808420546001600160a01b0391906200149e908316156200171c565b62000e6062001e51565b7f26f5fc8d4efd71a84c53331930e9e501a0e7f23ee9a4384ccb5b5f31d300578080546001019055600560005260026020527fb98b78633099fa36ed8b8680c4f8092689e1e04080eb9cbb077ca38a14d7e38480546001600160a01b0319166000805160206200865e833981519152179055600080516020620086de8339815191528180a46200153762002350565b62001b44565b600660009081527fe1f6b6a5fb7e47dad87547d4b0671e7e995a1dae22fbe5b3b5d10e2a77ed7b01805460ff191660011790557f25847c9ccf691da811a9f934d6b3b92e6062ef92feb71bf4cb08cbb4fad8d6525460166020527fc6a239f207aea309a1b4879cb5411b8facfc2bc1e4cc4717ff2598676c399b5f805490929160409190810190811062000d69576000805160206200863e83398151915262000d1f93600692620002f996556200163062000c71855195620015ff87620002aa565b8387528584526002602052808420546001600160a01b03919062001626908316156200171c565b62000e6062001ed0565b7f25aa483189eea11bdafa3b7873fe10d74e8c067ae4cf7bf5fd9d2577dd7d695b80546001019055600660005260026020527f59dd4b18488d12f51eda69757a0ed42a2010c14b564330cc74a06895e60c077b80546001600160a01b0319166000805160206200863e833981519152179055600080516020620086de8339815191528180a4620016bf620023e6565b62001b82565b15620016cd57565b60405162461bcd60e51b815260206004820152603260248201526000805160206200861e83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b156200172457565b60405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606490fd5b908160209103126200026d57516001600160e01b0319811681036200026d5790565b6001600160a01b03909116815260006020820181905260408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600160408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600260408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600360408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600460408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600560408201526080606082018190526200087d9291019062000a82565b6001600160a01b03909116815260006020820152600660408201526080606082018190526200087d9291019062000a82565b3d1562001927573d906001600160401b038211620002a457604051916200191b601f8201601f191660200184620002c6565b82523d6000602084013e565b606090565b803b1562001a235760206040518092816000816200195a630a85bd0160e11b9889835233600484016200178b565b03926001600160a01b03165af160009181620019ec575b50620019de5762001981620018e9565b80519081620019d95760405162461bcd60e51b815260206004820152603260248201526000805160206200861e83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b602001fd5b6001600160e01b0319161490565b62001a1391925060203d811162001a1b575b62001a0a8183620002c6565b81019062001769565b903862001971565b503d620019fe565b5050600190565b600080516020620086fe833981519152803b1562001a2357602060405180928160008162001a68630a85bd0160e11b988983523360048401620017bd565b03925af160009181620019ec5750620019de5762001981620018e9565b6000805160206200867e833981519152803b1562001a2357602060405180928160008162001a68630a85bd0160e11b988983523360048401620017ef565b6000805160206200873e833981519152803b1562001a2357602060405180928160008162001a68630a85bd0160e11b98898352336004840162001821565b735d2a610dfcff2b38e82df7f2c3c100cf6332527d803b1562001a2357602060405180928160008162001a68630a85bd0160e11b98898352336004840162001853565b6000805160206200865e833981519152803b1562001a2357602060405180928160008162001a68630a85bd0160e11b98898352336004840162001885565b6000805160206200863e833981519152803b1562001a2357602060405180928160008162001a68630a85bd0160e11b988983523360048401620018b7565b600854906000908180526020926009845280604084205568010000000000000000811015620002a457600181018060085581101562001c4a5760088352838320018290556001600160a01b0316908162001c2157505050620002f962001f75565b604091815260038352600782822054936006815283832085845281528284812055828052522055565b62001f4f565b600854600090600182526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a576001604092600883528483200155600080516020620086fe8339815191528152600383526007828220549360068152838320858452815260018484205560018352522055565b600854600090600282526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a5760026040926008835284832001556000805160206200867e8339815191528152600383526007828220549360068152838320858452815260028484205560028352522055565b600854600090600382526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a5760036040926008835284832001556000805160206200873e8339815191528152600383526007828220549360068152838320858452815260038484205560038352522055565b600854600090600482526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a576004604092600883528483200155735d2a610dfcff2b38e82df7f2c3c100cf6332527d8152600383526007828220549360068152838320858452815260048484205560048352522055565b600854600090600582526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a5760056040926008835284832001556000805160206200865e8339815191528152600383526007828220549360068152838320858452815260058484205560058352522055565b600854600090600682526020916009835281604082205568010000000000000000821015620002a457600182018060085582101562001c4a5760066040926008835284832001556000805160206200863e8339815191528152600383526007828220549360068152838320858452815260068484205560068352522055565b634e487b7160e01b600052603260045260246000fd5b60001981019190821162000d6957565b60088054600019919082810181811162000d6957600091828052600960205280604084205492101562001c4a578383528481602085200101549082101562001c4a5762001fd79084845280836020862001556000526009602052604060002090565b55600080526009602052807fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b5581549283156200202857808401938085101562001c4a578383526020832001015555565b634e487b7160e01b82526031600452602482fd5b65ffffffffffff804311620021355763ffffffff8091431611620020e1576200207c90620020736200206d62002699565b62002a72565b90431662002837565b5050600d602052600080516020620086be83398151915254600080516020620086fe8339815191526000527f91528cfbcf02e8bdd2032119620887b742bf0d5264d867c6aec3273764c871b854620002f9916001600160a01b03918216911662002505565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b65ffffffffffff804311620021355763ffffffff8091431611620020e157620021ba90620020736200206d62002699565b5050600d602052600080516020620086be833981519152546000805160206200867e8339815191526000527f90ebd8e8943ae84e37352d8f9b5ec6286c53bf2c5f49f58a520bed645d80285d54620002f9916001600160a01b03918216911662002505565b65ffffffffffff804311620021355763ffffffff8091431611620020e1576200225090620020736200206d62002699565b5050600d602052600080516020620086be833981519152546000805160206200873e8339815191526000527f6f7420a3bf5f659f66da61470606aa926dcaad448fe289394e68e1678fbfc84b54620002f9916001600160a01b03918216911662002505565b65ffffffffffff804311620021355763ffffffff8091431611620020e157620022e690620020736200206d62002699565b5050600d602052600080516020620086be83398151915254735d2a610dfcff2b38e82df7f2c3c100cf6332527d6000527f55fccfb8cec076b32e2f3a623080194f5717f4d0e68f66b11475afb0d5f05c7d54620002f9916001600160a01b03918216911662002505565b65ffffffffffff804311620021355763ffffffff8091431611620020e1576200238190620020736200206d62002699565b5050600d602052600080516020620086be833981519152546000805160206200865e8339815191526000527ff12336d992abbaef28dd80bdc4f4924d91b49a25551a9c9a4894d77853b15e1154620002f9916001600160a01b03918216911662002505565b65ffffffffffff804311620021355763ffffffff8091431611620020e1576200241790620020736200206d62002699565b5050600d602052600080516020620086be833981519152546000805160206200863e8339815191526000527f0373994cc7cad5706a8012bd6bc8c7cb29af41c0c8cbea3ed96eeb10fa267f2954620002f9916001600160a01b03918216911662002505565b65ffffffffffff90814311620021355763ffffffff8092431611620020e157620024b2620002f992620020736200206d62002699565b50506001600160a01b03908116908115620024f3575b600d602052600080516020620086be8339815191525460009283526040909220548116911662002505565b620024fd62002632565b5050620024c8565b6001600160a01b03808316929190811690818414158062002629575b6200252d575b50505050565b816200259b575b50508162002545575b808062002527565b6001600160a01b03166000908152600e602052604090206000805160206200875e83398151915290620025789062002667565b604080516001600160e01b039384168152919092166020820152a238806200253d565b6001600160a01b03166000908152600e6020526040902065ffffffffffff90814311620021355763ffffffff8092431611620020e1576000805160206200875e8339815191529181620025fc620025f66200260694620026d7565b62002a8b565b9143169062002972565b604080516001600160e01b039384168152919092166020820152a2388062002534565b50600162002521565b65ffffffffffff804311620021355763ffffffff8091431611620020e157620026639062002073620025f662002699565b9091565b65ffffffffffff804311620021355763ffffffff8091431611620020e15781620025fc6200206d6200266394620026d7565b600f5460009080620026ac575050600090565b60001991818381011162000d6957600f9052016000805160206200871e833981519152015460201c90565b805460009181620026ea57505050600090565b60001992828481011162000d695760209181522001015460201c90565b600f549068010000000000000000821015620002a4576001820180600f5582101562001c4a57600f600052805160209182015190911b63ffffffff191663ffffffff91909116176000805160206200871e83398151915290910155565b90815468010000000000000000811015620002a4576001810180845581101562001c4a57600092835260209283902082519284015190931b63ffffffff191663ffffffff9290921691909117910155565b604080519192919081016001600160401b03811182821017620002a457604052602081935463ffffffff81168352811c910152565b15620027f257565b60405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606490fd5b600f5491929180156200294357620029039181856200287f620028796200286060209662001f65565b600f6000526000805160206200871e8339815191520190565b620027b5565b926200288f845163ffffffff1690565b620028a863ffffffff91828416928391161115620027ea565b620028c4620028bb865163ffffffff1690565b63ffffffff1690565b03620029075750620028de62002860620028f59362001f65565b9063ffffffff82549181199060201b169116179055565b01516001600160e01b031690565b9190565b90506200293d9150620029296200291d620002ea565b63ffffffff9092168252565b6001600160e01b0387168185015262002707565b620028f5565b506200296c90620029576200291d620002ea565b6001600160e01b038416602082015262002707565b60009190565b9092919283825480151560001462002a4857926020929184620029ae62002879620029a1620029039862001f65565b8560005260206000200190565b93620029be855163ffffffff1690565b620029d763ffffffff91828416928391161115620027ea565b620029ea620028bb875163ffffffff1690565b0362002a125750620028f59262002a05620028de9262001f65565b9060005260206000200190565b9150506200293d9162002a3462002a28620002ea565b63ffffffff9093168352565b6001600160e01b0388168286015262002764565b50506200296c9162002a5d62002a28620002ea565b6001600160e01b038516602083015262002764565b6001600160e01b0390811660010190811162000d695790565b6001600160e01b039081166000190190811162000d69579056fe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610327578063040f15df14610322578063061ba2f11461031d57806306fdde0314610318578063081812fc14610313578063095ea7b31461030e57806318160ddd146103095780631998aeef146103045780631f88c9d0146102ff57806323b872dd146102fa5780632f745c59146102f55780633644e515146102f0578063379607f5146102eb57806338495761146102e65780633a46b1a8146102e15780633fc8cef3146102dc57806342842e0e146102d75780634bf5d7e9146102d25780634f6ccce7146102cd57806351c93569146102c8578063587cde1e146102c35780635c19a95c146102be5780636352211e146102b957806370a08231146102b4578063715018a6146102af5780637ecebe00146102aa57806384b0196e146102a55780638da5cb5b146102a05780638e539e8c1461029b5780638ff12b6d146102965780639051cce91461029157806391ddadf41461028c57806395d89b411461028757806396545927146102825780639ab24eb01461027d578063a0712d6814610278578063a22cb46514610273578063a5ad0edf1461026e578063b88d4fde14610269578063bfc12c0514610264578063c3cda5201461025f578063c6c034431461025a578063c87b56dd14610255578063d1d58b2514610250578063d3ea43501461024b578063e985e9c514610246578063f2fde38b14610241578063f86058011461023c5763fe8e66ed1461023757600080fd5b611dc8565b611d93565b611cd0565b611c73565b611c57565b611c39565b611982565b61195f565b611835565b611817565b6117b8565b61170a565b611622565b611553565b61150a565b611497565b611412565b6113e6565b611376565b611326565b61124b565b611222565b611160565b611126565b6110c8565b6110a5565b611087565b611065565b61102a565b610fc5565b610f1a565b610e6d565b610e45565b610e1c565b610d1a565b610ca2565b610a70565b610a55565b6109a2565b610979565b610841565b610699565b61067b565b6105a5565b610549565b61048c565b610455565b6103d6565b610343565b6001600160e01b031981160361033e57565b600080fd5b3461033e57602036600319011261033e5760206004356103628161032c565b63ffffffff60e01b1663780e9d6360e01b8114908115610388575b506040519015158152f35b6380ac58cd60e01b8114915081156103ba575b81156103a9575b503861037d565b6301ffc9a760e01b149050386103a2565b635b5e139f60e01b8114915061039b565b600091031261033e57565b3461033e57600036600319011261033e5760206103f1613e9a565b604051908152f35b60005b83811061040c5750506000910152565b81810151838201526020016103fc565b90602091610435815180928185528580860191016103f9565b601f01601f1916010190565b90602061045292818152019061041c565b90565b3461033e57602036600319011261033e57610488610474600435614765565b60405191829160208352602083019061041c565b0390f35b3461033e57600080600319360112610546576040518180546104ad8161234b565b8084529060019081811690811561051e57506001146104e3575b610488846104d781880382610b5d565b60405191829182610441565b93508180526020938483205b82841061050b5750505081610488936104d792820101936104c7565b80548585018701529285019281016104ef565b61048896506104d79450602092508593915060ff191682840152151560051b820101936104c7565b80fd5b3461033e57602036600319011261033e5760206105676004356123f7565b6040516001600160a01b039091168152f35b600435906001600160a01b038216820361033e57565b602435906001600160a01b038216820361033e57565b3461033e57604036600319011261033e576105be610579565b6024356105ca81612328565b916001600160a01b03808416908216811461062c576105fc936105f79133149081156105fe575b50612385565b612721565b005b6001600160a01b0316600090815260056020908152604080832033845290915290205460ff169050386105f1565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b3461033e57600036600319011261033e576020600854604051908152f35b600036600319011261033e576106b0341515613ef1565b6106b8613eba565b6106e26106db60016106d4846000526014602052604060002090565b01546129cf565b3411613f5d565b6107066106f9826000526014602052604060002090565b546001600160a01b031690565b6001600160a01b039061071d908216331415613fa0565b6107436107376106f9846000526014602052604060002090565b6001600160a01b031690565b6001610759846000526014602052604060002090565b015492346001610773836000526014602052604060002090565b01556107ac3361078d836000526014602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b6107b5816144ab565b60408051348152602081019290925233917f19421268847f42dd61705778018ddfc43bcdce8517e7a630acb12f122c7094819190a21690816107f357005b6105fc91615869565b90815180825260208080930193019160005b82811061081c575050505090565b83518552938101939281019260010161080e565b9060206104529281815201906107fc565b3461033e57602036600319011261033e5761085a610579565b610862613eba565b9061086c826131e1565b916000916001600160a01b0390811690835b8381106108cd578585610890816131e1565b9160005b8281106108a957604051806104888682610830565b806108b76108c892846138f1565b516108c282876138f1565b526138d8565b610894565b82826108e66106f9846000526014602052604060002090565b16148061091c575b610901575b6108fc906138d8565b61087e565b9361091481866108c26108fc948a6138f1565b9490506108f3565b5061093e6002610936836000526014602052604060002090565b015460ff1690565b156108ee565b606090600319011261033e576001600160a01b0390600435828116810361033e5791602435908116810361033e579060443590565b3461033e576105fc61098a36610944565b9161099d6109988433612528565b612423565b6125fa565b3461033e57604036600319011261033e576109bb610579565b602435906109c88161226a565b8210156109fc576001600160a01b031660009081526006602090815260408083209383529281529082902054915191825290f35b60405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608490fd5b3461033e57600036600319011261033e5760206103f1613089565b3461033e57602036600319011261033e576105fc60043561439f565b634e487b7160e01b600052604160045260246000fd5b6001600160401b038111610ab557604052565b610a8c565b604081019081106001600160401b03821117610ab557604052565b606081019081106001600160401b03821117610ab557604052565b602081019081106001600160401b03821117610ab557604052565b60c081019081106001600160401b03821117610ab557604052565b608081019081106001600160401b03821117610ab557604052565b61012081019081106001600160401b03821117610ab557604052565b90601f801991011681019081106001600160401b03821117610ab557604052565b60405190610b8b82610aba565b565b60405190610b8b82610ad5565b60405190610b8b82610b41565b6001600160401b038111610ab55760051b60200190565b6001600160401b038111610ab557601f01601f191660200190565b929192610be582610bbe565b91610bf36040519384610b5d565b82948184528183011161033e578281602093846000960137010152565b81601f8201121561033e57803590610c2782610ba7565b92604092610c3784519586610b5d565b808552602093848087019260051b8501019383851161033e57858101925b858410610c66575050505050505090565b83356001600160401b03811161033e57820185603f8201121561033e578791610c9787838786809601359101610bd9565b815201930192610c55565b3461033e57608036600319011261033e57600435600481101561033e576001600160401b039060243582811161033e57610ce0903690600401610c10565b60443583811161033e57610cf8903690600401610c10565b9060643593841161033e57610d146105fc943690600401610c10565b926136a4565b3461033e57604036600319011261033e57610d33610579565b60243590610d5265ffffffffffff610d4a436135d8565b168310611e4e565b6001600160a01b03166000908152600e6020526040812091610d739061363f565b91805482938160058111610dc4575b5090602094610d919284612e53565b80610dab5750505b6040516001600160e01b039091168152f35b91610db78492936129c0565b928152200154811c610d99565b94610dce8661341d565b8603958611610e1757602095610d919385875263ffffffff80838a8a2001541690851610600014610e055750915b91925094610d82565b929150610e11906129e3565b90610dfc565b612254565b3461033e57600036600319011261033e576013546040516001600160a01b039091168152602090f35b3461033e576105fc610e5636610944565b9060405192610e6484610af0565b60008452612485565b3461033e57600036600319011261033e574365ffffffffffff610e8f436135d8565b1603610eda57610488604051610ea481610aba565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015260405191829182610441565b60405162461bcd60e51b8152602060048201526018602482015277566f7465733a2062726f6b656e20636c6f636b206d6f646560401b6044820152606490fd5b3461033e57602036600319011261033e57600435600854811015610f6b5760086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30154604051908152602090f35b60405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608490fd5b3461033e57602036600319011261033e57600435806000526014602052610ff760ff6002604060002001541615613fec565b602454810190818111610e17576110196105fc92611013613eba565b1161407d565b600a546001600160a01b0316614224565b3461033e57602036600319011261033e5760206001600160a01b038061104e610579565b16600052600d825260406000205416604051908152f35b3461033e57602036600319011261033e576105fc611081610579565b33611ed4565b3461033e57602036600319011261033e576020610567600435612328565b3461033e57602036600319011261033e5760206103f16110c3610579565b61226a565b3461033e57600080600319360112610546576110e2611de3565b600a80546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b3461033e57602036600319011261033e576001600160a01b03611147610579565b1660005260106020526020604060002054604051908152f35b3461033e57600036600319011261033e576111f361119d7f0000000000000000000000000000000000000000000000000000000000000000613213565b6104886111c97f0000000000000000000000000000000000000000000000000000000000000000613307565b6112016111d46131c9565b91604051958695600f60f81b875260e0602088015260e087019061041c565b90858203604087015261041c565b90466060850152306080850152600060a085015283820360c08501526107fc565b3461033e57600036600319011261033e57600a546040516001600160a01b039091168152602090f35b3461033e57602036600319011261033e5761128260043561127d65ffffffffffff611275436135d8565b168210611e4e565b61363f565b600f549060008291600584116112cd575b61129d9350612dea565b6000816112b257505060405160008152602090f35b60206112be81936129c0565b91600f8152200154811c610d99565b91926112d88161341d565b8103908111610e1757600f8252600080516020615b0383398151915281015461129d949063ffffffff9081169085161015611314575091611293565b929150611320906129e3565b90611293565b3461033e57602036600319011261033e5760043560005260146020526060604060002060018060a01b038154169060ff600260018301549201541690604051928352602083015215156040820152f35b3461033e57602036600319011261033e576004356001600160401b0380821161033e573660238301121561033e57816004013590811161033e57600560243683831b850182011161033e5760005b8381106113cd57005b806113e083600193861b8801013561439f565b016113c4565b3461033e57600036600319011261033e576020611402436135d8565b65ffffffffffff60405191168152f35b3461033e57600080600319360112610546576040518160018054906114368261234b565b8085529181811690811561051e575060011461145c57610488846104d781880382610b5d565b80945082526020938483205b8284106114845750505081610488936104d792820101936104c7565b8054858501870152928501928101611468565b3461033e5760208060031936011261033e576114b46004356152a3565b604051918260009283915b600983106114cd5761036086f35b838251829087915b600383106114f1575050506060600192019201920191906114bf565b815160ff168152879360019093019291820191016114d5565b3461033e57602036600319011261033e576001600160a01b0361152b610579565b16600052600e602052602060018060e01b0361154a6040600020612a80565b16604051908152f35b3461033e57602036600319011261033e576004356000818152601460205260409020546001600160a01b031633036115d957806115ab6115a560026109366105fc956000526014602052604060002090565b15613fec565b6115c16115ba60245483614038565b1515614042565b6115d36115cc613eba565b821061407d565b33614224565b60405162461bcd60e51b81526020600482015260176024820152762cb7ba9030b932903737ba103a3432903bb4b73732b91760491b6044820152606490fd5b8015150361033e57565b3461033e57604036600319011261033e5761163b610579565b60243561164781611618565b6001600160a01b038216913383146116c957816116866116979233600052600560205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b604051901515815233907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190602090a3005b60405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606490fd5b3461033e57602036600319011261033e5760043560245480156117b357810661177b576117496115a56002610936846000526014602052604060002090565b6117546115cc613eba565b6014810661177257600a546105fc91906001600160a01b0316614224565b6105fc906140c0565b60405162461bcd60e51b815260206004820152601060248201526f24ba13b9903737ba1029bab73230bc9760811b6044820152606490fd5b6133fd565b3461033e57608036600319011261033e576117d1610579565b6117d961058f565b606435916001600160401b03831161033e573660238401121561033e5761180d6105fc933690602481600401359101610bd9565b9160443591612485565b3461033e57600036600319011261033e576020601254604051908152f35b3461033e5760c036600319011261033e5761184e610579565b6064359060243560443560ff8416840361033e5780421161191f576118f161191a916105fc95604051906118d9826118cb6020820195898b8860609194939260808201957fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf835260018060a01b0316602083015260408201520152565b03601f198101845283610b5d565b6118ec60a43593608435935190206131a3565b612eb5565b6001600160a01b0381166000908152601060205260409020805460018101909155909214611e91565b611ed4565b60405162461bcd60e51b8152602060048201526018602482015277159bdd195cce881cda59db985d1d5c9948195e1c1a5c995960421b6044820152606490fd5b3461033e57600036600319011261033e57602060ff602354166040519015158152f35b3461033e57602036600319011261033e5760043561199f81612785565b6119a890614d25565b6119b181614c4b565b6119ba90614c86565b805160ff166119c890613905565b5090602081015160ff166119db90613924565b5092604082015160ff166119ee90613943565b50916060015160ff16611a0090613962565b50611a0a82615374565b611a139061579e565b90611a1d83614765565b611a26906159ef565b92611a3090614d96565b604051707b202261747472696275746573223a205b60781b602082015296879691959160318801611a63916002016146e3565b611a6c90614d89565b611a78916002016146e3565b611a8190614d89565b611a8d916002016146e3565b611a9690614d89565b611aa2916002016146e3565b611aab90614d89565b7f7b2274726169745f74797065223a2022436f6c6f72222c202276616c7565223a815261101160f11b6020820152602201611ae5916146cc565b61227d60f01b815260020161174b60f21b81526002017f226465736372697074696f6e223a20224372656174656420627920746865676f81527f61742e777466222c2265787465726e616c5f75726c223a202268747470733a2f60208201527f2f746865676f61742e777466222c22696d616765223a2022646174613a696d6160408201527119d94bdcdd99cade1b5b0ed8985cd94d8d0b60721b6060820152607201611b91916146cc565b74222c226e616d65223a202254686520476f6174202360581b8152601501611bb8916146cc565b61227d60f01b81526002010390601f19918281018252611bd89082610b5d565b611be1906159ef565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000602082015291908290603d8201611c1b916146cc565b039081018252611c2b9082610b5d565b604051610488819282610441565b3461033e57602036600319011261033e5760206103f1600435614431565b3461033e57602036600319011261033e576105fc6004356144ab565b3461033e57604036600319011261033e57602060ff611cc4611c93610579565b611c9b61058f565b6001600160a01b0391821660009081526005865260408082209290931681526020919091522090565b54166040519015158152f35b3461033e57602036600319011261033e57611ce9610579565b611cf1611de3565b6001600160a01b03908116908115611d3f57600a80546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461033e57600036600319011261033e57611dac611de3565b6001602354611dbe60ff821615613892565b60ff191617602355005b3461033e57600036600319011261033e5760206103f1613eba565b600a546001600160a01b03163303611df757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b60405190611e4882610af0565b60008252565b15611e5557565b60405162461bcd60e51b81526020600482015260146024820152730566f7465733a20667574757265206c6f6f6b75760641b6044820152606490fd5b15611e9857565b60405162461bcd60e51b8152602060048201526014602482015273566f7465733a20696e76616c6964206e6f6e636560601b6044820152606490fd5b6001600160a01b038181166000818152600d6020526040812080548685166001600160a01b0319821681179092559095931693611f3a929091869186917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9080a461226a565b91838114158061205b575b611f50575b50505050565b80611fc1575b5082611f63575b80611f4a565b6001600160a01b03166000908152600e60205260409020600080516020615b2383398151915291611f9e91611f98909161356f565b906121a7565b604080516001600160e01b039384168152919092166020820152a2388080611f5d565b6001600160a01b0381166000908152600e60205260409020611fe28461356f565b611ffb65ffffffffffff611ff5436135d8565b1661363f565b6001600160e01b0391828061200f86612a80565b169116900392828411610e1757600080516020615b23833981519152936120529261203992612d04565b6040805192851683529316602082015291829190820190565b0390a238611f56565b50821515611f45565b6001600160a01b038083169291908116908184141580612161575b6120895750505050565b816120f0575b50508161209e575b8080611f4a565b6001600160a01b03166000908152600e60205260409020600080516020615b23833981519152906120ce90612169565b604080516001600160e01b039384168152919092166020820152a23880612097565b6001600160a01b03166000908152600e6020526040902061211a65ffffffffffff611ff5436135d8565b6001600160e01b03906000198261213085612a80565b160192828411610e1757600080516020615b23833981519152936121579261203992612d04565b0390a2388061208f565b50600161207f565b61217c65ffffffffffff611ff5436135d8565b6001600160e01b039060018261219185612a80565b1601918211610e17576121a392612d04565b9091565b906121bb65ffffffffffff611ff5436135d8565b6001600160e01b039182806121cf86612a80565b16911601918211610e17576121a392612d04565b6121f665ffffffffffff611ff5436135d8565b6001600160e01b03600181612209612a45565b1601908111610e17576121a391612be6565b61222e65ffffffffffff611ff5436135d8565b6001600160e01b0360001981612242612a45565b1601908111612254576121a391612be6565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0316801561228a57600052600360205260406000205490565b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608490fd5b156122e857565b60405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606490fd5b6000908152600260205260409020546001600160a01b03166104528115156122e1565b90600182811c9216801561237b575b602083101461236557565b634e487b7160e01b600052602260045260246000fd5b91607f169161235a565b1561238c57565b60405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608490fd5b61240861240382612785565b6122e1565b6000908152600460205260409020546001600160a01b031690565b1561242a57565b60405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608490fd5b91610b8b93916124ac9361249c6109988433612528565b6124a78383836125fa565b61296e565b612504565b60809060208152603260208201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60608201520190565b1561250b57565b60405162461bcd60e51b815280612524600482016124b1565b0390fd5b6001600160a01b038061253a84612328565b169281831692848414948515612570575b5050831561255a575b50505090565b612566919293506123f7565b1614388080612554565b60009081526005602090815260408083206001600160a01b03949094168352929052205460ff169350388061254b565b156125a757565b60405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608490fd5b61261e9261260781612328565b6001600160a01b03838116959091821686146125a0565b831680156126d057610b8b94612635838686614ed4565b61264b8161264561073786612328565b146125a0565b612672612662846000526004602052604060002090565b80546001600160a01b0319169055565b6001600160a01b038481166000908152600360209081526040808320805460001901905592881682528282208054600101905585825260029052206126b890869061078d565b600080516020615ae3833981519152600080a4615155565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b600082815260046020526040902080546001600160a01b0319166001600160a01b0383161790556001600160a01b038061275a84612328565b169116907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4565b6000908152600260205260409020546001600160a01b0316151590565b9081602091031261033e57516104528161032c565b610452939260809260018060a01b03168252600060208301526040820152816060820152019061041c565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526104529291019061041c565b6040513d6000823e3d90fd5b3d1561284a573d9061283082610bbe565b9161283e6040519384610b5d565b82523d6000602084013e565b606090565b9073cc44a5feb6ee172daaa31c1fee3fc1ce1654057f803b1561291257612894602091600093604051948580948193630a85bd0160e11b998a845233600485016127b7565b03925af1600091816128e2575b506128d4576128ae61281f565b805190816128cf5760405162461bcd60e51b815280612524600482016124b1565b602001fd5b6001600160e01b0319161490565b61290491925060203d811161290b575b6128fc8183610b5d565b8101906127a2565b90386128a1565b503d6128f2565b505050600190565b909190803b156129125761294c602091600093604051948580948193630a85bd0160e11b998a845233600485016127b7565b03926001600160a01b03165af1600091816128e257506128d4576128ae61281f565b92909190823b156129a15761294c926020926000604051809681958294630a85bd0160e11b9a8b855233600486016127e2565b50505050600190565b634e487b7160e01b600052603260045260246000fd5b600019810191908211610e1757565b9066038d7ea4c680008201809211610e1757565b9060018201809211610e1757565b9060028201809211610e1757565b9060208201809211610e1757565b9060d28201809211610e1757565b9060808201809211610e1757565b9060408201809211610e1757565b9060148201809211610e1757565b600f5460009080612a57575050600090565b600019918183810111610e1757600f905201600080516020615b03833981519152015460201c90565b805460009181612a9257505050600090565b600019928284810111610e175760209181522001015460201c90565b634e487b7160e01b600052600060045260246000fd5b600f5490600160401b821015610ab5576001820180600f55821015612b1957600f600052805160209182015190911b63ffffffff191663ffffffff9190911617600080516020615b0383398151915290910155565b6129aa565b908154600160401b811015610ab55760018101808455811015612b1957600092835260209283902082519284015190931b63ffffffff191663ffffffff9290921691909117910155565b90604051604081018181106001600160401b03821117610ab557604052602081935463ffffffff81168352811c910152565b15612ba157565b60405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606490fd5b600f549192918015612cda57612ca0918185612c26612c21612c096020966129c0565b600f600052600080516020615b038339815191520190565b612b68565b92612c35845163ffffffff1690565b612c4c63ffffffff91828416928391161115612b9a565b612c66612c5d865163ffffffff1690565b63ffffffff1690565b03612ca45750612c7b612c09612c92936129c0565b9063ffffffff82549181199060201b169116179055565b01516001600160e01b031690565b9190565b9050612cd59150612cc2612cb6610b7e565b63ffffffff9092168252565b6001600160e01b03871681850152612ac4565b612c92565b50612cfe90612cea612cb6610b7e565b6001600160e01b0384166020820152612ac4565b60009190565b90929192838254801515600014612dc557926020929184612d3a612c21612d2d612ca0986129c0565b8560005260206000200190565b93612d49855163ffffffff1690565b612d6063ffffffff91828416928391161115612b9a565b612d71612c5d875163ffffffff1690565b03612d945750612c9292612d87612c7b926129c0565b9060005260206000200190565b915050612cd591612db2612da6610b7e565b63ffffffff9093168352565b6001600160e01b03881682860152612b1e565b5050612cfe91612dd6612da6610b7e565b6001600160e01b0385166020830152612b1e565b905b828110612df857505090565b9091808216906001818418811c8301809311610e1757600f600052600080516020615b0383398151915283015463ffffffff9081169086161015612e40575050915b90612dec565b909392508101809111610e175790612e3a565b91905b838210612e635750505090565b909192808316906001818518811c8301809311610e175760008681526020902083015463ffffffff9081169085161015612ea2575050925b9190612e56565b909493508101809111610e175791612e9b565b916104529391612ec49361300c565b919091612ef1565b634e487b7160e01b600052602160045260246000fd5b60051115612eec57565b612ecc565b612efa81612ee2565b80612f025750565b612f0b81612ee2565b60018103612f535760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606490fd5b612f5c81612ee2565b60028103612fa95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606490fd5b80612fb5600392612ee2565b14612fbc57565b60405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608490fd5b9291906fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831161307d5791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa156130785781516001600160a01b03811615613072579190565b50600190565b612813565b50505050600090600390565b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316148061317a575b156130e4577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815261317481610b0b565b51902090565b507f000000000000000000000000000000000000000000000000000000000000000046146130bb565b6042906131ae613089565b906040519161190160f01b8352600283015260228201522090565b6040516131d581610af0565b60008152906000368137565b906131eb82610ba7565b6131f86040519182610b5d565b8281528092613209601f1991610ba7565b0190602036910137565b60ff811461324d5760ff811690601f821161323b576132306133bc565b918252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600b548160006132608361234b565b8083526001938085169081156132e65750600114613286575b5061045292500382610b5d565b600b60009081527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db994602093509091905b8183106132ce575050610452935082010138613279565b855487840185015294850194869450918301916132b7565b905061045294506020925060ff191682840152151560051b82010138613279565b60ff81146133245760ff811690601f821161323b576132306133bc565b50604051600c548160006133378361234b565b8083526001938085169081156132e6575060011461335c575061045292500382610b5d565b600c60009081527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c794602093509091905b8183106133a4575050610452935082010138613279565b8554878401850152948501948694509183019161338d565b604051906133c982610aba565b60208083523683820137565b906133df82610bbe565b6133ec6040519182610b5d565b8281528092613209601f1991610bbe565b634e487b7160e01b600052601260045260246000fd5b81156117b3570490565b801561355757806134f06134e96134df6134d56134cb6134c16134b76134ad60016104529a6000908b60801c8061354b575b508060401c8061353e575b508060201c80613531575b508060101c80613524575b508060081c80613517575b508060041c8061350a575b508060021c806134fd575b50821c6134f6575b811c1b6134a6818b613413565b0160011c90565b6134a6818a613413565b6134a68189613413565b6134a68188613413565b6134a68187613413565b6134a68186613413565b6134a68185613413565b8092613413565b9061355d565b8101613499565b6002915091019038613491565b6004915091019038613486565b600891509101903861347b565b6010915091019038613470565b6020915091019038613465565b604091509101903861345a565b9150506080903861344f565b50600090565b908082101561356a575090565b905090565b6001600160e01b0390818111613583571690565b60405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608490fd5b65ffffffffffff908181116135eb571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b63ffffffff90818111613650571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b939291936136b0611de3565b6136c68251865181149081613840575b5061384b565b6136e16136dc6136d860235460ff1690565b1590565b613892565b60005b825181101561383857613743906136fa836138e7565b826137485761373e61370c82866138f1565b51613717838a6138f1565b5161372284896138f1565b519061372c610b8d565b92835260208301526040820152613dab565b6138d8565b6136e4565b613751836138e7565b600183036137985761373e61376682866138f1565b51613771838a6138f1565b5161377c84896138f1565b5190613786610b8d565b92835260208301526040820152613cbc565b6137a1836138e7565b600283036137e85761373e6137b682866138f1565b516137c1838a6138f1565b516137cc84896138f1565b51906137d6610b8d565b92835260208301526040820152613bcd565b6137f1836138e7565b6003830361373e5761373e61380682866138f1565b51613811838a6138f1565b5161381c84896138f1565b5190613826610b8d565b92835260208301526040820152613aa3565b505050509050565b9050845114386136c0565b1561385257565b60405162461bcd60e51b8152602060048201526018602482015277082e4e4c2f240d8cadccee8d0e640daeae6e840dac2e8c6d60431b6044820152606490fd5b1561389957565b60405162461bcd60e51b815260206004820152601760248201527641727420697320616c726561647920636f6d706c65746560481b6044820152606490fd5b6000198114610e175760010190565b60041115612eec57565b8051821015612b195760209160051b010190565b601754811015612b195760176000526003602060002091020190600090565b601854811015612b195760186000526003602060002091020190600090565b601954811015612b195760196000526003602060002091020190600090565b601a54811015612b1957601a6000526003602060002091020190600090565b90601f811161398f57505050565b600091825260208220906020601f850160051c830194106139cb575b601f0160051c01915b8281106139c057505050565b8181556001016139b4565b90925082906139ab565b91909182516001600160401b038111610ab5576139fc816139f6845461234b565b84613981565b602080601f8311600114613a38575081929394600092613a2d575b50508160011b916000199060031b1c1916179055565b015190503880613a17565b90601f19831695613a4e85600052602060002090565b926000905b888210613a8b57505083600195969710613a72575b505050811b019055565b015160001960f88460031b161c19169055388080613a68565b80600185968294968601518155019501930190613a53565b6019549190600160401b831015610ab557613ac5600193848101601955613943565b919091613bc85780519384516001600160401b038111610ab557613af381613aed865461234b565b86613981565b6020958690601f8311600114613b505792610b8b96978360029694613b3c94604097600092613b45575b5050600019600383901b1c191690831b1787555b8301519086016139d5565b015191016139d5565b015190503880613b1d565b90601f19831691613b6687600052602060002090565b9260005b818110613bb357509484613b3c948294610b8b9b9c9460029a9860409a10613b9a575b505050811b018755613b31565b015160001960f88460031b161c19169055388080613b8d565b82840151855593860193928a01928a01613b6a565b612aae565b601a549190600160401b831015610ab557613bef600193848101601a55613962565b919091613bc85780519384516001600160401b038111610ab557613c1781613aed865461234b565b6020958690601f8311600114613c5e5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613c7487600052602060002090565b9260005b818110613ca757509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613c78565b6018549190600160401b831015610ab557613cde600193848101601855613924565b919091613bc85780519384516001600160401b038111610ab557613d0681613aed865461234b565b6020958690601f8311600114613d4d5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613d6387600052602060002090565b9260005b818110613d9657509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613d67565b6017549190600160401b831015610ab557613dcd600193848101601755613905565b919091613bc85780519384516001600160401b038111610ab557613df581613aed865461234b565b6020958690601f8311600114613e3c5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613e5287600052602060002090565b9260005b818110613e8557509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613e56565b6012544203428111610e175762015180900460018101809111610e175790565b613ec2613e9a565b806006019081600611610e1757613ed7613e9a565b9060245480156117b357600692040101809111610e175790565b15613ef857565b60405162461bcd60e51b815260206004820152603760248201527f596f75206d7573742073656e6420736f6d6520657468657220746f207061727460448201527634b1b4b830ba329034b7103a34329030bab1ba34b7b71760491b6064820152608490fd5b15613f6457565b60405162461bcd60e51b81526020600482015260146024820152732cb7bab9103134b21034b9903a37b7903637bb9760611b6044820152606490fd5b15613fa757565b60405162461bcd60e51b815260206004820152601b60248201527f596f752061726520616c7265616479207468652077696e6e65722e00000000006044820152606490fd5b15613ff357565b60405162461bcd60e51b815260206004820152601c60248201527f596f7520616c7265616479206d696e74656420796f7572204e46542e000000006044820152606490fd5b81156117b3570690565b1561404957565b60405162461bcd60e51b815260206004820152600c60248201526b24ba13b99029bab73230bc9760a11b6044820152606490fd5b1561408457565b60405162461bcd60e51b81526020600482015260146024820152732230bc903737ba103932b0b1b432b2103cb2ba1760611b6044820152606490fd5b600090808252601460205260026040832001600160ff198254161790556015602052604082205491601660205260408120918254938401809411610e1757610b8b936124ac9355806040519261411584610af0565b80845261412a61412483612785565b15614353565b61413382615051565b7f130d3b8ec5ca77745df8f9eefabec10d458057080e300991474408db5f897e855460008181527fdc8790dd48d9d7c4bd3f295ca5c205857bfaa48fc9197ec228cdb0e96e90034560209081526040808320869055858352600790915290205561419f61412483612785565b73cc44a5feb6ee172daaa31c1fee3fc1ce1654057f90818152600360205260408120600181540190556142056141df846000526002602052604060002090565b80546001600160a01b03191673cc44a5feb6ee172daaa31c1fee3fc1ce1654057f179055565b600080516020615ae38339815191528180a461421f6151b7565b61284f565b600091808352601460205260026040842001600160ff19825416179055601560205260408320546016602052604084208054918201809211610e1757556040519061426e82610af0565b8382526001600160a01b03831692831561430f57816124ac94610b8b9661429f61429a6136d885612785565b614353565b6142a98385614ff2565b6142b861429a6136d885612785565b6001600160a01b0384166000908152600360205260409020600181540190556142ef8461078d856000526002602052604060002090565b600080516020615ae38339815191528180a461430a81615238565b61291a565b606460405162461bcd60e51b815260206004820152602060248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152fd5b1561435a57565b60405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606490fd5b6143a881612785565b1561033e576001600160a01b036143be82612328565b16330361033e576143cd613eba565b81101561033e576143dd81614431565b9081159081156143ec57505050565b614400906000526016602052604060002090565b805490838201809211610e1757600093849384938493558290614428575b3390f11561307857565b506108fc61441e565b614439613eba565b6000199290838101908111610e17575b604060008281526015602052205415806144a2575b15614470578015610e17578301614449565b9092506000526015602052614495604060002054916000526016602052604060002090565b548103908111610e175790565b5080151561445e565b6144b3613eba565b811161033e57801561033e576000198101818111610e175760005260156020526040600020541580614553575b61453d575b6145016144f1826129c0565b6000526015602052604060002090565b549080600161451a826000526014602052604060002090565b0154048201809211610e175761453a906000526015602052604060002090565b55565b61454e614549826129c0565b6144ab565b6144e5565b50600181116144e0565b1561456457565b60405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420696e64657820666f72206172742e686561647300000000006044820152606490fd5b156145b057565b60405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420696e64657820666f72206172742e686f726e7300000000006044820152606490fd5b156145fc57565b60405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420696e64657820666f72206172742e626f64696573000000006044820152606490fd5b1561464857565b60405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e64657820666f72206172742e657965730000000000006044820152606490fd5b6004811015612b195760011b601b0190600090565b9060ff60405192548181168452818160081c16602085015260101c166040830152610b8b82610ad5565b906146df602092828151948592016103f9565b0190565b6000929181546146f28161234b565b9260019180831690811561474a575060011461470e5750505050565b90919293945060005260209081600020906000915b8583106147395750505050019038808080611f4a565b805485840152918301918101614723565b60ff1916845250505081151590910201915038808080611f4a565b61476d613eba565b8111156147799061407d565b61478281614c4b565b61478b90614c86565b9060ff9182815116601754116147a09061455d565b602081019183835116601854116147b6906145a9565b604082019284845116601954116147cc906145f5565b606083019185835116601a54116147e290614641565b6147eb906152a3565b9283516147f79061579e565b9460208501516148069061579e565b9660408601516148159061579e565b9560608101516148249061579e565b9060808101516148339061579e565b60a08201516148419061579e565b60c083015161484f9061579e565b9160e084015161485e9061579e565b93610100015161486d9061579e565b948689511661487b9061468d565b50614885906146a2565b61488e9061579e565b96808080808d511661489f9061468d565b506001016148ac906146a2565b6148b59061579e565b9b51166148c190613943565b509b51166148ce90613905565b509b51166148db90613924565b509b51166148e890613962565b509b6040519e8f9e8f60200161498690606f907f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323081527f30302f737667272076696577426f783d2730202d302e3520323820323827207360208201527f686170652d72656e646572696e673d2763726973704564676573273e3c73747960408201526e36329f10173198bdb9ba3937b5b29d60891b60608201520190565b61498f916146cc565b6d1dbe901731993db9ba3937b5b29d60911b8152600e016149af916146cc565b6d1dbe90173199bdb9ba3937b5b29d60911b8152600e016149cf916146cc565b6d1dbe9017319abdb9ba3937b5b29d60911b8152600e016149ef916146cc565b6d1dbe9017319b3db9ba3937b5b29d60911b8152600e01614a0f916146cc565b6d1dbe901732193db9ba3937b5b29d60911b8152600e01614a2f916146cc565b6d1dbe90173219bdb9ba3937b5b29d60911b8152600e01614a4f916146cc565b6d1dbe9017321a3db9ba3937b5b29d60911b8152600e01614a6f916146cc565b6d1dbe9017321b3db9ba3937b5b29d60911b8152600e01614a8f916146cc565b6d1dbe90173998bdb9ba3937b5b29d60911b8152600e01614aaf916146cc565b6d1dbe901739993db9ba3937b5b29d60911b8152600e01614acf916146cc565b7f3b7d203c2f7374796c653e3c7061746820636c6173733d2263312220643d224d81527f3020306832384d3020316832384d3020326832384d3020336832384d3020346860208201527f32384d3020356832384d3020366832384d3020376832384d3020386832384d3060408201527f20396832384d302031306832384d302031316832384d302031326832384d302060608201527f31336832384d302031346832384d302031356832384d302031366832384d302060808201527f31376832384d302031386832384d302031396832384d302032306832384d302060a08201527f32316832384d302032326832384d302032336832384d302032346832384d302060c082015277191ab4191c269810191b34191c269810191bb4191c11179f60411b60e082015260f801614c06916001016146e3565b614c12916001016146e3565b614c1e916001016146e3565b614c2a916001016146e3565b651e17b9bb339f60d11b815260060103601f19810182526104529082610b5d565b6040516020810191825266151a1951dbd85d60ca1b60408201526027815261317481610ad5565b60405190614c7f82610ad5565b6060368337565b6080604051614c9481610b26565b36903760405190614ca482610b26565b60803683376017549081156117b35760ff8282061683520460185480156117b35780820660ff16602084015261045291614d1b91614d0291614d1291614cee91613413565b613413565b60195490614ce9614d08614d028484614038565b60ff1690565b60ff166040890152565b601a5490614038565b60ff166060830152565b15614d2c57565b60405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608490fd5b600b60fa1b815260010190565b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015614ec6575b506d04ee2d6d415b85acef810000000080831015614eb7575b50662386f26fc1000080831015614ea8575b506305f5e10080831015614e99575b5061271080831015614e8a575b506064821015614e7a575b600a80921015614e70575b600190816021614e288287016133d5565b95860101905b614e3a575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215614e6b57919082614e2e565b614e33565b9160010191614e17565b9190606460029104910191614e0c565b60049193920491019138614e01565b60089193920491019138614df4565b60109193920491019138614de5565b60209193920491019138614dd3565b604093508104915038614dba565b9091906001600160a01b038082169182614f175750614ef283615051565b831680614f05575050610b8b91506150a9565b03614f0e575050565b610b8b91615019565b8185168303614f27575b50614ef2565b614f308161226a565b6000198101908111610e1757614f8860009286845260076020526040842054838103614f99575b5083614f6d886000526007602052604060002090565b556001600160a01b0316600090815260066020526040902090565b908252602052604081205538614f21565b868552600660205260408520848652602052614feb6040862054614fcf8460018060a01b03166000526006602052604060002090565b8388526020528060408820556000526007602052604060002090565b5538614f57565b90614ffc81615051565b6001600160a01b03821661501457610b8b91506150a9565b610b8b915b6040906150258161226a565b9260009160018060a01b0316825260066020528282208483526020528083832055815260076020522055565b60085481600052600960205280604060002055600160401b811015610ab5576001810180600855811015612b195760086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b60088054600019929083810190808211610e17576000928084526009602052816040852054931015612b195784845285826020862001015491831015612b1957839261510d61511e9387865280836020882001556000526009602052604060002090565b556000526009602052604060002090565b558154928315615141578084019380851015612b19578383526020832001015555565b634e487b7160e01b82526031600452602482fd5b610b8b916001600160a01b039182169190819083156151a8575b16918215615199575b600052600d6020528060406000205416916000526040600020541690612064565b6151a161221b565b5050615178565b6151b06121e3565b505061516f565b6151bf6121e3565b5050600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee5473cc44a5feb6ee172daaa31c1fee3fc1ce1654057f6000527fcdb666f48cce5d344caea1f88d15637636615b6e9563a95f2881914947b8cef554610b8b916001600160a01b039182169116612064565b610b8b906152446121e3565b50506001600160a01b03908116908115615294575b600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee54600092835260409092205481169116612064565b61529c61221b565b5050615259565b60409081516152b181610b41565b60005b61012081106153575750506152cb61534e91615374565b61531a6152d782615420565b916152e0610b9a565b946152ea82615500565b86526152f582615583565b6020870152615303826155fb565b9086015261531081615673565b6060860152615726565b608084015261532881615583565b60a0840152615336816155fb565b60c084015261534481615673565b60e0840152615726565b61010082015290565b602090845161536581610ad5565b606036823781840152016152b4565b606060405161538281610ad5565b36903760405190606082018281106001600160401b03821117610ab55760405260ff6153ad826153ee565b1682526105398101808211610e17576153c760ff916153ee565b16602083015262cc07c98101809111610e17576153e560ff916153ee565b16604082015290565b60ff90604051602081019182526020815261540881610aba565b5190201690565b60ff1660ff039060ff8211610e1757565b606060405161542e81610ad5565b36903760406153e581519261544284610ad5565b606036853760ff928184615459818095511661540f565b1686528261546c8160208401511661540f565b16602087015201511661540f565b600281901b91906001600160fe1b03811603610e1757565b90602b820291808304602b1490151715610e1757565b90607082029180830460701490151715610e1757565b90608882029180830460881490151715610e1757565b908160061b9180830460401490151715610e1757565b90602c820291808304602c1490151715610e1757565b606060405161550e81610ad5565b369037615519614c72565b9060ff80825116602b810290808204602b1490151715610e175781615564816040610452968261554d816155789804612a0d565b1689528261556a8161556481602086015116615492565b04612a0d565b1660208a0152015116615492565b1660ff166040830152565b606060405161559181610ad5565b36903761559c614c72565b9060ff80825116607081029080820460701490151715610e1757816155e781604061045296826155d0816155789804612a1b565b168952826155ed816155e7816020860151166154a8565b04612a1b565b1660208a01520151166154a8565b606060405161560981610ad5565b369037615614614c72565b9060ff80825116608881029080820460881490151715610e17578161565f8160406104529682615648816155789804612a29565b168952826156658161565f816020860151166154be565b04612a29565b1660208a01520151166154be565b606060405161568181610ad5565b36903761568c614c72565b908051613fc060ff82169160061b169080820460401490151715610e1757614d026157046156fd6156f860ff6040610452976156d96156d2614d028561571c9b04612a29565b60ff168b52565b615713615709614d026157046156fd6156f88860208801511660ff1690565b6154d4565b60ff900490565b612a29565b60ff1660208c0152565b01511660ff1690565b60ff166040830152565b606060405161573481610ad5565b36903761573f614c72565b9060ff80825116602c810290808204602c1490151715610e17578161578a8160406104529682615773816155789804612a37565b168952826157908161578a816020860151166154ea565b04612a37565b1660208a01520151166154ea565b6104526157ae60ff835116614d96565b61584660266157d260ff60406157c98260208a015116614d96565b97015116614d96565b604051958694630e4cec4560e31b60208701526157f981518092602060248a0191016103f9565b850190600b60fa1b9182602482015261581c8251809360206025850191016103f9565b0190602582015261583682518093602086850191016103f9565b0101600190602960f81b81520190565b03601f198101835282610b5d565b9081602091031261033e575161045281611618565b6158766136d8838361596b565b61587e575050565b60135461589590610737906001600160a01b031681565b803b1561033e5760008391600460405180968193630d0e30db60e41b83525af19182156130785761591793602093615952575b506013546158e090610737906001600160a01b031681565b60405163a9059cbb60e01b81526001600160a01b039092166004830152602482019290925292839190829060009082906044820190565b03925af18015613078576159285750565b6159489060203d811161594b575b6159408183610b5d565b810190615854565b50565b503d615936565b8061595f61596592610aa2565b806103cb565b386158c8565b600080809381938260405161597f81610af0565b52617530f161598c61281f565b5090565b6040519061599d82610ad5565b604082527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040837f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201520152565b805115615ad9576159fe615990565b615a1a615a15615a0e84516129f1565b6003900490565b61547a565b91615a2c615a27846129ff565b6133d5565b92835280815182019060208501935b828210615a7d57505050600390510680600114615a6c57600214615a5d575090565b603d60f81b6000199091015290565b50613d3d60f01b6001199091015290565b90919360049060038094019384516001603f81818460121c16880101519260f893841b8652828282600c1c1689010151841b8387015282828260061c1689010151841b60028701521686010151901b9082015201939190615a3b565b50610452611e3b56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724a264697066735822122069471a2bbcd63354abdfa9c574c19631f108d0d8dfaff9c47154b889ea8cb0e964736f6c634300081200334552433732313a207472616e7366657220746f206e6f6e204552433732315265000000000000000000000000c2b35534e47cdf3d787e01630129631d8270abfb000000000000000000000000a73827d96540e1d8cacd48017a2eb08b0e073e27000000000000000000000000184fd7ace17722da2ffd9dc1f951da8283253cdfac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29eeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0000000000000000000000000e802eef59d855375e4826123a4145b829bc3f838d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802000000000000000000000000f728ce79c82bb99335e0a781cac0254b6a9aeb37dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724

Deployed Bytecode

0x6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610327578063040f15df14610322578063061ba2f11461031d57806306fdde0314610318578063081812fc14610313578063095ea7b31461030e57806318160ddd146103095780631998aeef146103045780631f88c9d0146102ff57806323b872dd146102fa5780632f745c59146102f55780633644e515146102f0578063379607f5146102eb57806338495761146102e65780633a46b1a8146102e15780633fc8cef3146102dc57806342842e0e146102d75780634bf5d7e9146102d25780634f6ccce7146102cd57806351c93569146102c8578063587cde1e146102c35780635c19a95c146102be5780636352211e146102b957806370a08231146102b4578063715018a6146102af5780637ecebe00146102aa57806384b0196e146102a55780638da5cb5b146102a05780638e539e8c1461029b5780638ff12b6d146102965780639051cce91461029157806391ddadf41461028c57806395d89b411461028757806396545927146102825780639ab24eb01461027d578063a0712d6814610278578063a22cb46514610273578063a5ad0edf1461026e578063b88d4fde14610269578063bfc12c0514610264578063c3cda5201461025f578063c6c034431461025a578063c87b56dd14610255578063d1d58b2514610250578063d3ea43501461024b578063e985e9c514610246578063f2fde38b14610241578063f86058011461023c5763fe8e66ed1461023757600080fd5b611dc8565b611d93565b611cd0565b611c73565b611c57565b611c39565b611982565b61195f565b611835565b611817565b6117b8565b61170a565b611622565b611553565b61150a565b611497565b611412565b6113e6565b611376565b611326565b61124b565b611222565b611160565b611126565b6110c8565b6110a5565b611087565b611065565b61102a565b610fc5565b610f1a565b610e6d565b610e45565b610e1c565b610d1a565b610ca2565b610a70565b610a55565b6109a2565b610979565b610841565b610699565b61067b565b6105a5565b610549565b61048c565b610455565b6103d6565b610343565b6001600160e01b031981160361033e57565b600080fd5b3461033e57602036600319011261033e5760206004356103628161032c565b63ffffffff60e01b1663780e9d6360e01b8114908115610388575b506040519015158152f35b6380ac58cd60e01b8114915081156103ba575b81156103a9575b503861037d565b6301ffc9a760e01b149050386103a2565b635b5e139f60e01b8114915061039b565b600091031261033e57565b3461033e57600036600319011261033e5760206103f1613e9a565b604051908152f35b60005b83811061040c5750506000910152565b81810151838201526020016103fc565b90602091610435815180928185528580860191016103f9565b601f01601f1916010190565b90602061045292818152019061041c565b90565b3461033e57602036600319011261033e57610488610474600435614765565b60405191829160208352602083019061041c565b0390f35b3461033e57600080600319360112610546576040518180546104ad8161234b565b8084529060019081811690811561051e57506001146104e3575b610488846104d781880382610b5d565b60405191829182610441565b93508180526020938483205b82841061050b5750505081610488936104d792820101936104c7565b80548585018701529285019281016104ef565b61048896506104d79450602092508593915060ff191682840152151560051b820101936104c7565b80fd5b3461033e57602036600319011261033e5760206105676004356123f7565b6040516001600160a01b039091168152f35b600435906001600160a01b038216820361033e57565b602435906001600160a01b038216820361033e57565b3461033e57604036600319011261033e576105be610579565b6024356105ca81612328565b916001600160a01b03808416908216811461062c576105fc936105f79133149081156105fe575b50612385565b612721565b005b6001600160a01b0316600090815260056020908152604080832033845290915290205460ff169050386105f1565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b3461033e57600036600319011261033e576020600854604051908152f35b600036600319011261033e576106b0341515613ef1565b6106b8613eba565b6106e26106db60016106d4846000526014602052604060002090565b01546129cf565b3411613f5d565b6107066106f9826000526014602052604060002090565b546001600160a01b031690565b6001600160a01b039061071d908216331415613fa0565b6107436107376106f9846000526014602052604060002090565b6001600160a01b031690565b6001610759846000526014602052604060002090565b015492346001610773836000526014602052604060002090565b01556107ac3361078d836000526014602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b6107b5816144ab565b60408051348152602081019290925233917f19421268847f42dd61705778018ddfc43bcdce8517e7a630acb12f122c7094819190a21690816107f357005b6105fc91615869565b90815180825260208080930193019160005b82811061081c575050505090565b83518552938101939281019260010161080e565b9060206104529281815201906107fc565b3461033e57602036600319011261033e5761085a610579565b610862613eba565b9061086c826131e1565b916000916001600160a01b0390811690835b8381106108cd578585610890816131e1565b9160005b8281106108a957604051806104888682610830565b806108b76108c892846138f1565b516108c282876138f1565b526138d8565b610894565b82826108e66106f9846000526014602052604060002090565b16148061091c575b610901575b6108fc906138d8565b61087e565b9361091481866108c26108fc948a6138f1565b9490506108f3565b5061093e6002610936836000526014602052604060002090565b015460ff1690565b156108ee565b606090600319011261033e576001600160a01b0390600435828116810361033e5791602435908116810361033e579060443590565b3461033e576105fc61098a36610944565b9161099d6109988433612528565b612423565b6125fa565b3461033e57604036600319011261033e576109bb610579565b602435906109c88161226a565b8210156109fc576001600160a01b031660009081526006602090815260408083209383529281529082902054915191825290f35b60405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608490fd5b3461033e57600036600319011261033e5760206103f1613089565b3461033e57602036600319011261033e576105fc60043561439f565b634e487b7160e01b600052604160045260246000fd5b6001600160401b038111610ab557604052565b610a8c565b604081019081106001600160401b03821117610ab557604052565b606081019081106001600160401b03821117610ab557604052565b602081019081106001600160401b03821117610ab557604052565b60c081019081106001600160401b03821117610ab557604052565b608081019081106001600160401b03821117610ab557604052565b61012081019081106001600160401b03821117610ab557604052565b90601f801991011681019081106001600160401b03821117610ab557604052565b60405190610b8b82610aba565b565b60405190610b8b82610ad5565b60405190610b8b82610b41565b6001600160401b038111610ab55760051b60200190565b6001600160401b038111610ab557601f01601f191660200190565b929192610be582610bbe565b91610bf36040519384610b5d565b82948184528183011161033e578281602093846000960137010152565b81601f8201121561033e57803590610c2782610ba7565b92604092610c3784519586610b5d565b808552602093848087019260051b8501019383851161033e57858101925b858410610c66575050505050505090565b83356001600160401b03811161033e57820185603f8201121561033e578791610c9787838786809601359101610bd9565b815201930192610c55565b3461033e57608036600319011261033e57600435600481101561033e576001600160401b039060243582811161033e57610ce0903690600401610c10565b60443583811161033e57610cf8903690600401610c10565b9060643593841161033e57610d146105fc943690600401610c10565b926136a4565b3461033e57604036600319011261033e57610d33610579565b60243590610d5265ffffffffffff610d4a436135d8565b168310611e4e565b6001600160a01b03166000908152600e6020526040812091610d739061363f565b91805482938160058111610dc4575b5090602094610d919284612e53565b80610dab5750505b6040516001600160e01b039091168152f35b91610db78492936129c0565b928152200154811c610d99565b94610dce8661341d565b8603958611610e1757602095610d919385875263ffffffff80838a8a2001541690851610600014610e055750915b91925094610d82565b929150610e11906129e3565b90610dfc565b612254565b3461033e57600036600319011261033e576013546040516001600160a01b039091168152602090f35b3461033e576105fc610e5636610944565b9060405192610e6484610af0565b60008452612485565b3461033e57600036600319011261033e574365ffffffffffff610e8f436135d8565b1603610eda57610488604051610ea481610aba565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015260405191829182610441565b60405162461bcd60e51b8152602060048201526018602482015277566f7465733a2062726f6b656e20636c6f636b206d6f646560401b6044820152606490fd5b3461033e57602036600319011261033e57600435600854811015610f6b5760086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30154604051908152602090f35b60405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608490fd5b3461033e57602036600319011261033e57600435806000526014602052610ff760ff6002604060002001541615613fec565b602454810190818111610e17576110196105fc92611013613eba565b1161407d565b600a546001600160a01b0316614224565b3461033e57602036600319011261033e5760206001600160a01b038061104e610579565b16600052600d825260406000205416604051908152f35b3461033e57602036600319011261033e576105fc611081610579565b33611ed4565b3461033e57602036600319011261033e576020610567600435612328565b3461033e57602036600319011261033e5760206103f16110c3610579565b61226a565b3461033e57600080600319360112610546576110e2611de3565b600a80546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b3461033e57602036600319011261033e576001600160a01b03611147610579565b1660005260106020526020604060002054604051908152f35b3461033e57600036600319011261033e576111f361119d7f546865476f617400000000000000000000000000000000000000000000000007613213565b6104886111c97f3100000000000000000000000000000000000000000000000000000000000001613307565b6112016111d46131c9565b91604051958695600f60f81b875260e0602088015260e087019061041c565b90858203604087015261041c565b90466060850152306080850152600060a085015283820360c08501526107fc565b3461033e57600036600319011261033e57600a546040516001600160a01b039091168152602090f35b3461033e57602036600319011261033e5761128260043561127d65ffffffffffff611275436135d8565b168210611e4e565b61363f565b600f549060008291600584116112cd575b61129d9350612dea565b6000816112b257505060405160008152602090f35b60206112be81936129c0565b91600f8152200154811c610d99565b91926112d88161341d565b8103908111610e1757600f8252600080516020615b0383398151915281015461129d949063ffffffff9081169085161015611314575091611293565b929150611320906129e3565b90611293565b3461033e57602036600319011261033e5760043560005260146020526060604060002060018060a01b038154169060ff600260018301549201541690604051928352602083015215156040820152f35b3461033e57602036600319011261033e576004356001600160401b0380821161033e573660238301121561033e57816004013590811161033e57600560243683831b850182011161033e5760005b8381106113cd57005b806113e083600193861b8801013561439f565b016113c4565b3461033e57600036600319011261033e576020611402436135d8565b65ffffffffffff60405191168152f35b3461033e57600080600319360112610546576040518160018054906114368261234b565b8085529181811690811561051e575060011461145c57610488846104d781880382610b5d565b80945082526020938483205b8284106114845750505081610488936104d792820101936104c7565b8054858501870152928501928101611468565b3461033e5760208060031936011261033e576114b46004356152a3565b604051918260009283915b600983106114cd5761036086f35b838251829087915b600383106114f1575050506060600192019201920191906114bf565b815160ff168152879360019093019291820191016114d5565b3461033e57602036600319011261033e576001600160a01b0361152b610579565b16600052600e602052602060018060e01b0361154a6040600020612a80565b16604051908152f35b3461033e57602036600319011261033e576004356000818152601460205260409020546001600160a01b031633036115d957806115ab6115a560026109366105fc956000526014602052604060002090565b15613fec565b6115c16115ba60245483614038565b1515614042565b6115d36115cc613eba565b821061407d565b33614224565b60405162461bcd60e51b81526020600482015260176024820152762cb7ba9030b932903737ba103a3432903bb4b73732b91760491b6044820152606490fd5b8015150361033e57565b3461033e57604036600319011261033e5761163b610579565b60243561164781611618565b6001600160a01b038216913383146116c957816116866116979233600052600560205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b604051901515815233907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190602090a3005b60405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606490fd5b3461033e57602036600319011261033e5760043560245480156117b357810661177b576117496115a56002610936846000526014602052604060002090565b6117546115cc613eba565b6014810661177257600a546105fc91906001600160a01b0316614224565b6105fc906140c0565b60405162461bcd60e51b815260206004820152601060248201526f24ba13b9903737ba1029bab73230bc9760811b6044820152606490fd5b6133fd565b3461033e57608036600319011261033e576117d1610579565b6117d961058f565b606435916001600160401b03831161033e573660238401121561033e5761180d6105fc933690602481600401359101610bd9565b9160443591612485565b3461033e57600036600319011261033e576020601254604051908152f35b3461033e5760c036600319011261033e5761184e610579565b6064359060243560443560ff8416840361033e5780421161191f576118f161191a916105fc95604051906118d9826118cb6020820195898b8860609194939260808201957fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf835260018060a01b0316602083015260408201520152565b03601f198101845283610b5d565b6118ec60a43593608435935190206131a3565b612eb5565b6001600160a01b0381166000908152601060205260409020805460018101909155909214611e91565b611ed4565b60405162461bcd60e51b8152602060048201526018602482015277159bdd195cce881cda59db985d1d5c9948195e1c1a5c995960421b6044820152606490fd5b3461033e57600036600319011261033e57602060ff602354166040519015158152f35b3461033e57602036600319011261033e5760043561199f81612785565b6119a890614d25565b6119b181614c4b565b6119ba90614c86565b805160ff166119c890613905565b5090602081015160ff166119db90613924565b5092604082015160ff166119ee90613943565b50916060015160ff16611a0090613962565b50611a0a82615374565b611a139061579e565b90611a1d83614765565b611a26906159ef565b92611a3090614d96565b604051707b202261747472696275746573223a205b60781b602082015296879691959160318801611a63916002016146e3565b611a6c90614d89565b611a78916002016146e3565b611a8190614d89565b611a8d916002016146e3565b611a9690614d89565b611aa2916002016146e3565b611aab90614d89565b7f7b2274726169745f74797065223a2022436f6c6f72222c202276616c7565223a815261101160f11b6020820152602201611ae5916146cc565b61227d60f01b815260020161174b60f21b81526002017f226465736372697074696f6e223a20224372656174656420627920746865676f81527f61742e777466222c2265787465726e616c5f75726c223a202268747470733a2f60208201527f2f746865676f61742e777466222c22696d616765223a2022646174613a696d6160408201527119d94bdcdd99cade1b5b0ed8985cd94d8d0b60721b6060820152607201611b91916146cc565b74222c226e616d65223a202254686520476f6174202360581b8152601501611bb8916146cc565b61227d60f01b81526002010390601f19918281018252611bd89082610b5d565b611be1906159ef565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000602082015291908290603d8201611c1b916146cc565b039081018252611c2b9082610b5d565b604051610488819282610441565b3461033e57602036600319011261033e5760206103f1600435614431565b3461033e57602036600319011261033e576105fc6004356144ab565b3461033e57604036600319011261033e57602060ff611cc4611c93610579565b611c9b61058f565b6001600160a01b0391821660009081526005865260408082209290931681526020919091522090565b54166040519015158152f35b3461033e57602036600319011261033e57611ce9610579565b611cf1611de3565b6001600160a01b03908116908115611d3f57600a80546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461033e57600036600319011261033e57611dac611de3565b6001602354611dbe60ff821615613892565b60ff191617602355005b3461033e57600036600319011261033e5760206103f1613eba565b600a546001600160a01b03163303611df757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b60405190611e4882610af0565b60008252565b15611e5557565b60405162461bcd60e51b81526020600482015260146024820152730566f7465733a20667574757265206c6f6f6b75760641b6044820152606490fd5b15611e9857565b60405162461bcd60e51b8152602060048201526014602482015273566f7465733a20696e76616c6964206e6f6e636560601b6044820152606490fd5b6001600160a01b038181166000818152600d6020526040812080548685166001600160a01b0319821681179092559095931693611f3a929091869186917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9080a461226a565b91838114158061205b575b611f50575b50505050565b80611fc1575b5082611f63575b80611f4a565b6001600160a01b03166000908152600e60205260409020600080516020615b2383398151915291611f9e91611f98909161356f565b906121a7565b604080516001600160e01b039384168152919092166020820152a2388080611f5d565b6001600160a01b0381166000908152600e60205260409020611fe28461356f565b611ffb65ffffffffffff611ff5436135d8565b1661363f565b6001600160e01b0391828061200f86612a80565b169116900392828411610e1757600080516020615b23833981519152936120529261203992612d04565b6040805192851683529316602082015291829190820190565b0390a238611f56565b50821515611f45565b6001600160a01b038083169291908116908184141580612161575b6120895750505050565b816120f0575b50508161209e575b8080611f4a565b6001600160a01b03166000908152600e60205260409020600080516020615b23833981519152906120ce90612169565b604080516001600160e01b039384168152919092166020820152a23880612097565b6001600160a01b03166000908152600e6020526040902061211a65ffffffffffff611ff5436135d8565b6001600160e01b03906000198261213085612a80565b160192828411610e1757600080516020615b23833981519152936121579261203992612d04565b0390a2388061208f565b50600161207f565b61217c65ffffffffffff611ff5436135d8565b6001600160e01b039060018261219185612a80565b1601918211610e17576121a392612d04565b9091565b906121bb65ffffffffffff611ff5436135d8565b6001600160e01b039182806121cf86612a80565b16911601918211610e17576121a392612d04565b6121f665ffffffffffff611ff5436135d8565b6001600160e01b03600181612209612a45565b1601908111610e17576121a391612be6565b61222e65ffffffffffff611ff5436135d8565b6001600160e01b0360001981612242612a45565b1601908111612254576121a391612be6565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0316801561228a57600052600360205260406000205490565b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608490fd5b156122e857565b60405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606490fd5b6000908152600260205260409020546001600160a01b03166104528115156122e1565b90600182811c9216801561237b575b602083101461236557565b634e487b7160e01b600052602260045260246000fd5b91607f169161235a565b1561238c57565b60405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608490fd5b61240861240382612785565b6122e1565b6000908152600460205260409020546001600160a01b031690565b1561242a57565b60405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608490fd5b91610b8b93916124ac9361249c6109988433612528565b6124a78383836125fa565b61296e565b612504565b60809060208152603260208201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60608201520190565b1561250b57565b60405162461bcd60e51b815280612524600482016124b1565b0390fd5b6001600160a01b038061253a84612328565b169281831692848414948515612570575b5050831561255a575b50505090565b612566919293506123f7565b1614388080612554565b60009081526005602090815260408083206001600160a01b03949094168352929052205460ff169350388061254b565b156125a757565b60405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608490fd5b61261e9261260781612328565b6001600160a01b03838116959091821686146125a0565b831680156126d057610b8b94612635838686614ed4565b61264b8161264561073786612328565b146125a0565b612672612662846000526004602052604060002090565b80546001600160a01b0319169055565b6001600160a01b038481166000908152600360209081526040808320805460001901905592881682528282208054600101905585825260029052206126b890869061078d565b600080516020615ae3833981519152600080a4615155565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b600082815260046020526040902080546001600160a01b0319166001600160a01b0383161790556001600160a01b038061275a84612328565b169116907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4565b6000908152600260205260409020546001600160a01b0316151590565b9081602091031261033e57516104528161032c565b610452939260809260018060a01b03168252600060208301526040820152816060820152019061041c565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526104529291019061041c565b6040513d6000823e3d90fd5b3d1561284a573d9061283082610bbe565b9161283e6040519384610b5d565b82523d6000602084013e565b606090565b9073cc44a5feb6ee172daaa31c1fee3fc1ce1654057f803b1561291257612894602091600093604051948580948193630a85bd0160e11b998a845233600485016127b7565b03925af1600091816128e2575b506128d4576128ae61281f565b805190816128cf5760405162461bcd60e51b815280612524600482016124b1565b602001fd5b6001600160e01b0319161490565b61290491925060203d811161290b575b6128fc8183610b5d565b8101906127a2565b90386128a1565b503d6128f2565b505050600190565b909190803b156129125761294c602091600093604051948580948193630a85bd0160e11b998a845233600485016127b7565b03926001600160a01b03165af1600091816128e257506128d4576128ae61281f565b92909190823b156129a15761294c926020926000604051809681958294630a85bd0160e11b9a8b855233600486016127e2565b50505050600190565b634e487b7160e01b600052603260045260246000fd5b600019810191908211610e1757565b9066038d7ea4c680008201809211610e1757565b9060018201809211610e1757565b9060028201809211610e1757565b9060208201809211610e1757565b9060d28201809211610e1757565b9060808201809211610e1757565b9060408201809211610e1757565b9060148201809211610e1757565b600f5460009080612a57575050600090565b600019918183810111610e1757600f905201600080516020615b03833981519152015460201c90565b805460009181612a9257505050600090565b600019928284810111610e175760209181522001015460201c90565b634e487b7160e01b600052600060045260246000fd5b600f5490600160401b821015610ab5576001820180600f55821015612b1957600f600052805160209182015190911b63ffffffff191663ffffffff9190911617600080516020615b0383398151915290910155565b6129aa565b908154600160401b811015610ab55760018101808455811015612b1957600092835260209283902082519284015190931b63ffffffff191663ffffffff9290921691909117910155565b90604051604081018181106001600160401b03821117610ab557604052602081935463ffffffff81168352811c910152565b15612ba157565b60405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606490fd5b600f549192918015612cda57612ca0918185612c26612c21612c096020966129c0565b600f600052600080516020615b038339815191520190565b612b68565b92612c35845163ffffffff1690565b612c4c63ffffffff91828416928391161115612b9a565b612c66612c5d865163ffffffff1690565b63ffffffff1690565b03612ca45750612c7b612c09612c92936129c0565b9063ffffffff82549181199060201b169116179055565b01516001600160e01b031690565b9190565b9050612cd59150612cc2612cb6610b7e565b63ffffffff9092168252565b6001600160e01b03871681850152612ac4565b612c92565b50612cfe90612cea612cb6610b7e565b6001600160e01b0384166020820152612ac4565b60009190565b90929192838254801515600014612dc557926020929184612d3a612c21612d2d612ca0986129c0565b8560005260206000200190565b93612d49855163ffffffff1690565b612d6063ffffffff91828416928391161115612b9a565b612d71612c5d875163ffffffff1690565b03612d945750612c9292612d87612c7b926129c0565b9060005260206000200190565b915050612cd591612db2612da6610b7e565b63ffffffff9093168352565b6001600160e01b03881682860152612b1e565b5050612cfe91612dd6612da6610b7e565b6001600160e01b0385166020830152612b1e565b905b828110612df857505090565b9091808216906001818418811c8301809311610e1757600f600052600080516020615b0383398151915283015463ffffffff9081169086161015612e40575050915b90612dec565b909392508101809111610e175790612e3a565b91905b838210612e635750505090565b909192808316906001818518811c8301809311610e175760008681526020902083015463ffffffff9081169085161015612ea2575050925b9190612e56565b909493508101809111610e175791612e9b565b916104529391612ec49361300c565b919091612ef1565b634e487b7160e01b600052602160045260246000fd5b60051115612eec57565b612ecc565b612efa81612ee2565b80612f025750565b612f0b81612ee2565b60018103612f535760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606490fd5b612f5c81612ee2565b60028103612fa95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606490fd5b80612fb5600392612ee2565b14612fbc57565b60405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608490fd5b9291906fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831161307d5791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa156130785781516001600160a01b03811615613072579190565b50600190565b612813565b50505050600090600390565b307f0000000000000000000000004c20d92dd450f4dcc23be4f4a014d5e13a3e37936001600160a01b0316148061317a575b156130e4577f03f21daedd5b775b8c87176a415317f62fcafb8b41adcf6c7f72e6c8d43e291590565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f336d8d56a22928814c2b44d791f67cb12f3d3b6496219bbdd50d42b63948364e60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815261317481610b0b565b51902090565b507f000000000000000000000000000000000000000000000000000000000000000146146130bb565b6042906131ae613089565b906040519161190160f01b8352600283015260228201522090565b6040516131d581610af0565b60008152906000368137565b906131eb82610ba7565b6131f86040519182610b5d565b8281528092613209601f1991610ba7565b0190602036910137565b60ff811461324d5760ff811690601f821161323b576132306133bc565b918252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600b548160006132608361234b565b8083526001938085169081156132e65750600114613286575b5061045292500382610b5d565b600b60009081527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db994602093509091905b8183106132ce575050610452935082010138613279565b855487840185015294850194869450918301916132b7565b905061045294506020925060ff191682840152151560051b82010138613279565b60ff81146133245760ff811690601f821161323b576132306133bc565b50604051600c548160006133378361234b565b8083526001938085169081156132e6575060011461335c575061045292500382610b5d565b600c60009081527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c794602093509091905b8183106133a4575050610452935082010138613279565b8554878401850152948501948694509183019161338d565b604051906133c982610aba565b60208083523683820137565b906133df82610bbe565b6133ec6040519182610b5d565b8281528092613209601f1991610bbe565b634e487b7160e01b600052601260045260246000fd5b81156117b3570490565b801561355757806134f06134e96134df6134d56134cb6134c16134b76134ad60016104529a6000908b60801c8061354b575b508060401c8061353e575b508060201c80613531575b508060101c80613524575b508060081c80613517575b508060041c8061350a575b508060021c806134fd575b50821c6134f6575b811c1b6134a6818b613413565b0160011c90565b6134a6818a613413565b6134a68189613413565b6134a68188613413565b6134a68187613413565b6134a68186613413565b6134a68185613413565b8092613413565b9061355d565b8101613499565b6002915091019038613491565b6004915091019038613486565b600891509101903861347b565b6010915091019038613470565b6020915091019038613465565b604091509101903861345a565b9150506080903861344f565b50600090565b908082101561356a575090565b905090565b6001600160e01b0390818111613583571690565b60405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608490fd5b65ffffffffffff908181116135eb571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608490fd5b63ffffffff90818111613650571690565b60405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608490fd5b939291936136b0611de3565b6136c68251865181149081613840575b5061384b565b6136e16136dc6136d860235460ff1690565b1590565b613892565b60005b825181101561383857613743906136fa836138e7565b826137485761373e61370c82866138f1565b51613717838a6138f1565b5161372284896138f1565b519061372c610b8d565b92835260208301526040820152613dab565b6138d8565b6136e4565b613751836138e7565b600183036137985761373e61376682866138f1565b51613771838a6138f1565b5161377c84896138f1565b5190613786610b8d565b92835260208301526040820152613cbc565b6137a1836138e7565b600283036137e85761373e6137b682866138f1565b516137c1838a6138f1565b516137cc84896138f1565b51906137d6610b8d565b92835260208301526040820152613bcd565b6137f1836138e7565b6003830361373e5761373e61380682866138f1565b51613811838a6138f1565b5161381c84896138f1565b5190613826610b8d565b92835260208301526040820152613aa3565b505050509050565b9050845114386136c0565b1561385257565b60405162461bcd60e51b8152602060048201526018602482015277082e4e4c2f240d8cadccee8d0e640daeae6e840dac2e8c6d60431b6044820152606490fd5b1561389957565b60405162461bcd60e51b815260206004820152601760248201527641727420697320616c726561647920636f6d706c65746560481b6044820152606490fd5b6000198114610e175760010190565b60041115612eec57565b8051821015612b195760209160051b010190565b601754811015612b195760176000526003602060002091020190600090565b601854811015612b195760186000526003602060002091020190600090565b601954811015612b195760196000526003602060002091020190600090565b601a54811015612b1957601a6000526003602060002091020190600090565b90601f811161398f57505050565b600091825260208220906020601f850160051c830194106139cb575b601f0160051c01915b8281106139c057505050565b8181556001016139b4565b90925082906139ab565b91909182516001600160401b038111610ab5576139fc816139f6845461234b565b84613981565b602080601f8311600114613a38575081929394600092613a2d575b50508160011b916000199060031b1c1916179055565b015190503880613a17565b90601f19831695613a4e85600052602060002090565b926000905b888210613a8b57505083600195969710613a72575b505050811b019055565b015160001960f88460031b161c19169055388080613a68565b80600185968294968601518155019501930190613a53565b6019549190600160401b831015610ab557613ac5600193848101601955613943565b919091613bc85780519384516001600160401b038111610ab557613af381613aed865461234b565b86613981565b6020958690601f8311600114613b505792610b8b96978360029694613b3c94604097600092613b45575b5050600019600383901b1c191690831b1787555b8301519086016139d5565b015191016139d5565b015190503880613b1d565b90601f19831691613b6687600052602060002090565b9260005b818110613bb357509484613b3c948294610b8b9b9c9460029a9860409a10613b9a575b505050811b018755613b31565b015160001960f88460031b161c19169055388080613b8d565b82840151855593860193928a01928a01613b6a565b612aae565b601a549190600160401b831015610ab557613bef600193848101601a55613962565b919091613bc85780519384516001600160401b038111610ab557613c1781613aed865461234b565b6020958690601f8311600114613c5e5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613c7487600052602060002090565b9260005b818110613ca757509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613c78565b6018549190600160401b831015610ab557613cde600193848101601855613924565b919091613bc85780519384516001600160401b038111610ab557613d0681613aed865461234b565b6020958690601f8311600114613d4d5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613d6387600052602060002090565b9260005b818110613d9657509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613d67565b6017549190600160401b831015610ab557613dcd600193848101601755613905565b919091613bc85780519384516001600160401b038111610ab557613df581613aed865461234b565b6020958690601f8311600114613e3c5792610b8b96978360029694613b3c94604097600092613b45575050600019600383901b1c191690831b1787558301519086016139d5565b90601f19831691613e5287600052602060002090565b9260005b818110613e8557509484613b3c948294610b8b9b9c9460029a9860409a10613b9a57505050811b018755613b31565b82840151855593860193928a01928a01613e56565b6012544203428111610e175762015180900460018101809111610e175790565b613ec2613e9a565b806006019081600611610e1757613ed7613e9a565b9060245480156117b357600692040101809111610e175790565b15613ef857565b60405162461bcd60e51b815260206004820152603760248201527f596f75206d7573742073656e6420736f6d6520657468657220746f207061727460448201527634b1b4b830ba329034b7103a34329030bab1ba34b7b71760491b6064820152608490fd5b15613f6457565b60405162461bcd60e51b81526020600482015260146024820152732cb7bab9103134b21034b9903a37b7903637bb9760611b6044820152606490fd5b15613fa757565b60405162461bcd60e51b815260206004820152601b60248201527f596f752061726520616c7265616479207468652077696e6e65722e00000000006044820152606490fd5b15613ff357565b60405162461bcd60e51b815260206004820152601c60248201527f596f7520616c7265616479206d696e74656420796f7572204e46542e000000006044820152606490fd5b81156117b3570690565b1561404957565b60405162461bcd60e51b815260206004820152600c60248201526b24ba13b99029bab73230bc9760a11b6044820152606490fd5b1561408457565b60405162461bcd60e51b81526020600482015260146024820152732230bc903737ba103932b0b1b432b2103cb2ba1760611b6044820152606490fd5b600090808252601460205260026040832001600160ff198254161790556015602052604082205491601660205260408120918254938401809411610e1757610b8b936124ac9355806040519261411584610af0565b80845261412a61412483612785565b15614353565b61413382615051565b7f130d3b8ec5ca77745df8f9eefabec10d458057080e300991474408db5f897e855460008181527fdc8790dd48d9d7c4bd3f295ca5c205857bfaa48fc9197ec228cdb0e96e90034560209081526040808320869055858352600790915290205561419f61412483612785565b73cc44a5feb6ee172daaa31c1fee3fc1ce1654057f90818152600360205260408120600181540190556142056141df846000526002602052604060002090565b80546001600160a01b03191673cc44a5feb6ee172daaa31c1fee3fc1ce1654057f179055565b600080516020615ae38339815191528180a461421f6151b7565b61284f565b600091808352601460205260026040842001600160ff19825416179055601560205260408320546016602052604084208054918201809211610e1757556040519061426e82610af0565b8382526001600160a01b03831692831561430f57816124ac94610b8b9661429f61429a6136d885612785565b614353565b6142a98385614ff2565b6142b861429a6136d885612785565b6001600160a01b0384166000908152600360205260409020600181540190556142ef8461078d856000526002602052604060002090565b600080516020615ae38339815191528180a461430a81615238565b61291a565b606460405162461bcd60e51b815260206004820152602060248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152fd5b1561435a57565b60405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606490fd5b6143a881612785565b1561033e576001600160a01b036143be82612328565b16330361033e576143cd613eba565b81101561033e576143dd81614431565b9081159081156143ec57505050565b614400906000526016602052604060002090565b805490838201809211610e1757600093849384938493558290614428575b3390f11561307857565b506108fc61441e565b614439613eba565b6000199290838101908111610e17575b604060008281526015602052205415806144a2575b15614470578015610e17578301614449565b9092506000526015602052614495604060002054916000526016602052604060002090565b548103908111610e175790565b5080151561445e565b6144b3613eba565b811161033e57801561033e576000198101818111610e175760005260156020526040600020541580614553575b61453d575b6145016144f1826129c0565b6000526015602052604060002090565b549080600161451a826000526014602052604060002090565b0154048201809211610e175761453a906000526015602052604060002090565b55565b61454e614549826129c0565b6144ab565b6144e5565b50600181116144e0565b1561456457565b60405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420696e64657820666f72206172742e686561647300000000006044820152606490fd5b156145b057565b60405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420696e64657820666f72206172742e686f726e7300000000006044820152606490fd5b156145fc57565b60405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420696e64657820666f72206172742e626f64696573000000006044820152606490fd5b1561464857565b60405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e64657820666f72206172742e657965730000000000006044820152606490fd5b6004811015612b195760011b601b0190600090565b9060ff60405192548181168452818160081c16602085015260101c166040830152610b8b82610ad5565b906146df602092828151948592016103f9565b0190565b6000929181546146f28161234b565b9260019180831690811561474a575060011461470e5750505050565b90919293945060005260209081600020906000915b8583106147395750505050019038808080611f4a565b805485840152918301918101614723565b60ff1916845250505081151590910201915038808080611f4a565b61476d613eba565b8111156147799061407d565b61478281614c4b565b61478b90614c86565b9060ff9182815116601754116147a09061455d565b602081019183835116601854116147b6906145a9565b604082019284845116601954116147cc906145f5565b606083019185835116601a54116147e290614641565b6147eb906152a3565b9283516147f79061579e565b9460208501516148069061579e565b9660408601516148159061579e565b9560608101516148249061579e565b9060808101516148339061579e565b60a08201516148419061579e565b60c083015161484f9061579e565b9160e084015161485e9061579e565b93610100015161486d9061579e565b948689511661487b9061468d565b50614885906146a2565b61488e9061579e565b96808080808d511661489f9061468d565b506001016148ac906146a2565b6148b59061579e565b9b51166148c190613943565b509b51166148ce90613905565b509b51166148db90613924565b509b51166148e890613962565b509b6040519e8f9e8f60200161498690606f907f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323081527f30302f737667272076696577426f783d2730202d302e3520323820323827207360208201527f686170652d72656e646572696e673d2763726973704564676573273e3c73747960408201526e36329f10173198bdb9ba3937b5b29d60891b60608201520190565b61498f916146cc565b6d1dbe901731993db9ba3937b5b29d60911b8152600e016149af916146cc565b6d1dbe90173199bdb9ba3937b5b29d60911b8152600e016149cf916146cc565b6d1dbe9017319abdb9ba3937b5b29d60911b8152600e016149ef916146cc565b6d1dbe9017319b3db9ba3937b5b29d60911b8152600e01614a0f916146cc565b6d1dbe901732193db9ba3937b5b29d60911b8152600e01614a2f916146cc565b6d1dbe90173219bdb9ba3937b5b29d60911b8152600e01614a4f916146cc565b6d1dbe9017321a3db9ba3937b5b29d60911b8152600e01614a6f916146cc565b6d1dbe9017321b3db9ba3937b5b29d60911b8152600e01614a8f916146cc565b6d1dbe90173998bdb9ba3937b5b29d60911b8152600e01614aaf916146cc565b6d1dbe901739993db9ba3937b5b29d60911b8152600e01614acf916146cc565b7f3b7d203c2f7374796c653e3c7061746820636c6173733d2263312220643d224d81527f3020306832384d3020316832384d3020326832384d3020336832384d3020346860208201527f32384d3020356832384d3020366832384d3020376832384d3020386832384d3060408201527f20396832384d302031306832384d302031316832384d302031326832384d302060608201527f31336832384d302031346832384d302031356832384d302031366832384d302060808201527f31376832384d302031386832384d302031396832384d302032306832384d302060a08201527f32316832384d302032326832384d302032336832384d302032346832384d302060c082015277191ab4191c269810191b34191c269810191bb4191c11179f60411b60e082015260f801614c06916001016146e3565b614c12916001016146e3565b614c1e916001016146e3565b614c2a916001016146e3565b651e17b9bb339f60d11b815260060103601f19810182526104529082610b5d565b6040516020810191825266151a1951dbd85d60ca1b60408201526027815261317481610ad5565b60405190614c7f82610ad5565b6060368337565b6080604051614c9481610b26565b36903760405190614ca482610b26565b60803683376017549081156117b35760ff8282061683520460185480156117b35780820660ff16602084015261045291614d1b91614d0291614d1291614cee91613413565b613413565b60195490614ce9614d08614d028484614038565b60ff1690565b60ff166040890152565b601a5490614038565b60ff166060830152565b15614d2c57565b60405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608490fd5b600b60fa1b815260010190565b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015614ec6575b506d04ee2d6d415b85acef810000000080831015614eb7575b50662386f26fc1000080831015614ea8575b506305f5e10080831015614e99575b5061271080831015614e8a575b506064821015614e7a575b600a80921015614e70575b600190816021614e288287016133d5565b95860101905b614e3a575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215614e6b57919082614e2e565b614e33565b9160010191614e17565b9190606460029104910191614e0c565b60049193920491019138614e01565b60089193920491019138614df4565b60109193920491019138614de5565b60209193920491019138614dd3565b604093508104915038614dba565b9091906001600160a01b038082169182614f175750614ef283615051565b831680614f05575050610b8b91506150a9565b03614f0e575050565b610b8b91615019565b8185168303614f27575b50614ef2565b614f308161226a565b6000198101908111610e1757614f8860009286845260076020526040842054838103614f99575b5083614f6d886000526007602052604060002090565b556001600160a01b0316600090815260066020526040902090565b908252602052604081205538614f21565b868552600660205260408520848652602052614feb6040862054614fcf8460018060a01b03166000526006602052604060002090565b8388526020528060408820556000526007602052604060002090565b5538614f57565b90614ffc81615051565b6001600160a01b03821661501457610b8b91506150a9565b610b8b915b6040906150258161226a565b9260009160018060a01b0316825260066020528282208483526020528083832055815260076020522055565b60085481600052600960205280604060002055600160401b811015610ab5576001810180600855811015612b195760086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b60088054600019929083810190808211610e17576000928084526009602052816040852054931015612b195784845285826020862001015491831015612b1957839261510d61511e9387865280836020882001556000526009602052604060002090565b556000526009602052604060002090565b558154928315615141578084019380851015612b19578383526020832001015555565b634e487b7160e01b82526031600452602482fd5b610b8b916001600160a01b039182169190819083156151a8575b16918215615199575b600052600d6020528060406000205416916000526040600020541690612064565b6151a161221b565b5050615178565b6151b06121e3565b505061516f565b6151bf6121e3565b5050600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee5473cc44a5feb6ee172daaa31c1fee3fc1ce1654057f6000527fcdb666f48cce5d344caea1f88d15637636615b6e9563a95f2881914947b8cef554610b8b916001600160a01b039182169116612064565b610b8b906152446121e3565b50506001600160a01b03908116908115615294575b600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee54600092835260409092205481169116612064565b61529c61221b565b5050615259565b60409081516152b181610b41565b60005b61012081106153575750506152cb61534e91615374565b61531a6152d782615420565b916152e0610b9a565b946152ea82615500565b86526152f582615583565b6020870152615303826155fb565b9086015261531081615673565b6060860152615726565b608084015261532881615583565b60a0840152615336816155fb565b60c084015261534481615673565b60e0840152615726565b61010082015290565b602090845161536581610ad5565b606036823781840152016152b4565b606060405161538281610ad5565b36903760405190606082018281106001600160401b03821117610ab55760405260ff6153ad826153ee565b1682526105398101808211610e17576153c760ff916153ee565b16602083015262cc07c98101809111610e17576153e560ff916153ee565b16604082015290565b60ff90604051602081019182526020815261540881610aba565b5190201690565b60ff1660ff039060ff8211610e1757565b606060405161542e81610ad5565b36903760406153e581519261544284610ad5565b606036853760ff928184615459818095511661540f565b1686528261546c8160208401511661540f565b16602087015201511661540f565b600281901b91906001600160fe1b03811603610e1757565b90602b820291808304602b1490151715610e1757565b90607082029180830460701490151715610e1757565b90608882029180830460881490151715610e1757565b908160061b9180830460401490151715610e1757565b90602c820291808304602c1490151715610e1757565b606060405161550e81610ad5565b369037615519614c72565b9060ff80825116602b810290808204602b1490151715610e175781615564816040610452968261554d816155789804612a0d565b1689528261556a8161556481602086015116615492565b04612a0d565b1660208a0152015116615492565b1660ff166040830152565b606060405161559181610ad5565b36903761559c614c72565b9060ff80825116607081029080820460701490151715610e1757816155e781604061045296826155d0816155789804612a1b565b168952826155ed816155e7816020860151166154a8565b04612a1b565b1660208a01520151166154a8565b606060405161560981610ad5565b369037615614614c72565b9060ff80825116608881029080820460881490151715610e17578161565f8160406104529682615648816155789804612a29565b168952826156658161565f816020860151166154be565b04612a29565b1660208a01520151166154be565b606060405161568181610ad5565b36903761568c614c72565b908051613fc060ff82169160061b169080820460401490151715610e1757614d026157046156fd6156f860ff6040610452976156d96156d2614d028561571c9b04612a29565b60ff168b52565b615713615709614d026157046156fd6156f88860208801511660ff1690565b6154d4565b60ff900490565b612a29565b60ff1660208c0152565b01511660ff1690565b60ff166040830152565b606060405161573481610ad5565b36903761573f614c72565b9060ff80825116602c810290808204602c1490151715610e17578161578a8160406104529682615773816155789804612a37565b168952826157908161578a816020860151166154ea565b04612a37565b1660208a01520151166154ea565b6104526157ae60ff835116614d96565b61584660266157d260ff60406157c98260208a015116614d96565b97015116614d96565b604051958694630e4cec4560e31b60208701526157f981518092602060248a0191016103f9565b850190600b60fa1b9182602482015261581c8251809360206025850191016103f9565b0190602582015261583682518093602086850191016103f9565b0101600190602960f81b81520190565b03601f198101835282610b5d565b9081602091031261033e575161045281611618565b6158766136d8838361596b565b61587e575050565b60135461589590610737906001600160a01b031681565b803b1561033e5760008391600460405180968193630d0e30db60e41b83525af19182156130785761591793602093615952575b506013546158e090610737906001600160a01b031681565b60405163a9059cbb60e01b81526001600160a01b039092166004830152602482019290925292839190829060009082906044820190565b03925af18015613078576159285750565b6159489060203d811161594b575b6159408183610b5d565b810190615854565b50565b503d615936565b8061595f61596592610aa2565b806103cb565b386158c8565b600080809381938260405161597f81610af0565b52617530f161598c61281f565b5090565b6040519061599d82610ad5565b604082527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040837f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201520152565b805115615ad9576159fe615990565b615a1a615a15615a0e84516129f1565b6003900490565b61547a565b91615a2c615a27846129ff565b6133d5565b92835280815182019060208501935b828210615a7d57505050600390510680600114615a6c57600214615a5d575090565b603d60f81b6000199091015290565b50613d3d60f01b6001199091015290565b90919360049060038094019384516001603f81818460121c16880101519260f893841b8652828282600c1c1689010151841b8387015282828260061c1689010151841b60028701521686010151901b9082015201939190615a3b565b50610452611e3b56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724a264697066735822122069471a2bbcd63354abdfa9c574c19631f108d0d8dfaff9c47154b889ea8cb0e964736f6c63430008120033

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.