ETH Price: $3,000.38 (-0.46%)

Contract

0x0e4EE35190f16EFdFd1aa9BE802cA546FCCE5a81

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Stake372789822026-01-29 1:15:076 mins ago1769649307IN
0x0e4EE351...6FCCE5a81
0 ETH0.000010020.04525
Stake372788152026-01-29 1:13:448 mins ago1769649224IN
0x0e4EE351...6FCCE5a81
0 ETH0.000007980.04525
Unstake Batch372763832026-01-29 0:56:2325 mins ago1769648183IN
0x0e4EE351...6FCCE5a81
0 ETH0.000013540.04525
Stake372751992026-01-29 0:47:5233 mins ago1769647672IN
0x0e4EE351...6FCCE5a81
0 ETH0.000008070.04525
Unstake372730942026-01-29 0:32:2149 mins ago1769646741IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006960.04525
Unstake372730392026-01-29 0:32:0149 mins ago1769646721IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006870.04525
Unstake372730092026-01-29 0:31:4849 mins ago1769646708IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006720.04525
Unstake372729522026-01-29 0:31:1950 mins ago1769646679IN
0x0e4EE351...6FCCE5a81
0 ETH0.00000970.04525
Stake372727232026-01-29 0:29:3552 mins ago1769646575IN
0x0e4EE351...6FCCE5a81
0 ETH0.000005610.04525
Stake372723882026-01-29 0:27:0254 mins ago1769646422IN
0x0e4EE351...6FCCE5a81
0 ETH0.000005610.04525
Stake372723562026-01-29 0:26:4954 mins ago1769646409IN
0x0e4EE351...6FCCE5a81
0 ETH0.000005610.04525
Stake372723312026-01-29 0:26:3855 mins ago1769646398IN
0x0e4EE351...6FCCE5a81
0 ETH0.00000570.04525
Unstake372721622026-01-29 0:25:1956 mins ago1769646319IN
0x0e4EE351...6FCCE5a81
0 ETH0.000008040.04525
Stake372716912026-01-29 0:21:431 hr ago1769646103IN
0x0e4EE351...6FCCE5a81
0 ETH0.00000570.04525
Stake372716392026-01-29 0:21:241 hr ago1769646084IN
0x0e4EE351...6FCCE5a81
0 ETH0.000005610.04525
Stake372716082026-01-29 0:21:111 hr ago1769646071IN
0x0e4EE351...6FCCE5a81
0 ETH0.000008080.04525
Unstake372702032026-01-29 0:11:011 hr ago1769645461IN
0x0e4EE351...6FCCE5a81
0 ETH0.000010020.04525
Stake372593412026-01-28 22:46:382 hrs ago1769640398IN
0x0e4EE351...6FCCE5a81
0 ETH0.000008430.04525
Stake372588732026-01-28 22:43:002 hrs ago1769640180IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006070.04525
Stake Batch372587622026-01-28 22:42:122 hrs ago1769640132IN
0x0e4EE351...6FCCE5a81
0 ETH0.000012040.04525
Stake372586452026-01-28 22:41:212 hrs ago1769640081IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006230.04525
Stake372584032026-01-28 22:39:372 hrs ago1769639977IN
0x0e4EE351...6FCCE5a81
0 ETH0.000007980.04525
Unstake372529712026-01-28 22:01:523 hrs ago1769637712IN
0x0e4EE351...6FCCE5a81
0 ETH0.000008640.04525
Stake Batch372527552026-01-28 22:00:313 hrs ago1769637631IN
0x0e4EE351...6FCCE5a81
0 ETH0.000014110.04525
Stake372482172026-01-28 21:30:323 hrs ago1769635832IN
0x0e4EE351...6FCCE5a81
0 ETH0.000006970.04525
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
366919382026-01-26 1:15:583 days ago1769390158  Contract Creation0 ETH
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BearishHibearnation

Compiler Version
v0.8.28+commit.7893614a

ZkSolc Version
v1.5.10

Optimization Enabled:
Yes with Mode 3

Other Settings:
paris EvmVersion
File 1 of 13 : BearishHibearnation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {Ownable} from "solady/src/auth/Ownable.sol";
import {ReentrancyGuard} from "solady/src/utils/ReentrancyGuard.sol";
import {EIP712} from "solady/src/utils/EIP712.sol";
import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol";
import {SafeTransferLib} from "solady/src/utils/ext/zksync/SafeTransferLib.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IHibearnation} from "./interfaces/IHibearnation.sol";

/**
 * @title BearishHibearnation
 * @author @bearish_af
 * @notice NFT staking contract with checkpoint-based accruals and server-signed claims.
 * @dev Staking accrues NFT-seconds (time × staked count) per address. Reward credits
 *      are derived as NFT-seconds × ratePerSecond. Claims are validated via EIP-712
 *      signatures from a trusted claim signer, with rewards paid from a treasury.
 */
contract BearishHibearnation is
    Ownable,
    ReentrancyGuard,
    EIP712,
    IHibearnation
{
    using EnumerableSet for EnumerableSet.UintSet;
    using SafeTransferLib for address;

    /// @notice EIP-712 typehash for claim signatures
    bytes32 public constant CLAIM_TYPEHASH =
        keccak256(
            "Claim(address to,uint256 amount,uint256 deadline,uint256 nonce)"
        );

    /// @notice Default emission rate (~1,000 BURR/NFT/year)
    uint256 public constant DEFAULT_RATE_PER_SECOND = 31_709_791_983_764;

    /// @notice DN404 unit representing 1 NFT in ERC20 terms (10,001 × 10^18)
    uint256 public constant DN404_UNIT = 10_001 * 1e18;

    /// @notice The ERC721 NFT contract for staking
    IERC721 public immutable nftContract;

    /// @notice The ERC20 reward token address (DN404)
    address public immutable rewardToken;

    /// @notice Treasury address that holds and pays out rewards
    address public treasury;

    /// @notice Address authorized to sign claim messages
    address public claimSigner;

    /// @notice Secondary admin for emergency operations
    address public moderator;

    /// @notice Emission rate in reward tokens per NFT-second
    uint256 public ratePerSecond;

    /// @notice Whether staking operations are paused
    bool public paused;

    /// @notice Whether claims are enabled
    bool public claimsEnabled;

    /// @notice Stake info by token ID
    mapping(uint256 => StakeInfo) public stakes;

    /// @notice Set of staked token IDs per address
    mapping(address => EnumerableSet.UintSet) private _stakedTokens;

    /// @notice Total number of NFTs currently staked
    uint256 public totalStaked;

    /// @notice Accumulated NFT-seconds per address (rate-independent)
    mapping(address => uint256) public accruedNFTSeconds;

    /// @notice Last checkpoint timestamp per address
    mapping(address => uint48) public lastCheckpoint;

    /// @notice Records depositor for NFTs sent via safeTransfer (not stake())
    mapping(uint256 => address) public untrackedDepositor;

    /// @notice Cumulative claimed amount per address
    mapping(address => uint256) public claimedAmount;

    /// @notice Claim nonce per address (prevents replay)
    mapping(address => uint256) public nonces;

    /// @dev Reverts if contract is paused
    modifier whenNotPaused() {
        if (paused) revert Paused();
        _;
    }

    /// @dev Reverts if caller is not owner or moderator
    modifier onlyOwnerOrModerator() {
        if (msg.sender != owner() && msg.sender != moderator)
            revert Unauthorized();
        _;
    }

    /**
     * @notice Initializes the staking contract
     * @param _nftContract Address of the ERC721 NFT contract to stake
     * @param _rewardToken Address of the DN404/ERC20 reward token
     * @param _treasury Address holding reward tokens (must approve this contract)
     * @param _owner Contract owner address
     * @param _claimSigner Address authorized to sign claim messages
     * @param _moderator Secondary admin for emergency functions (can be zero)
     * @param _ratePerSecond Initial emission rate per NFT-second
     */
    constructor(
        address _nftContract,
        address _rewardToken,
        address _treasury,
        address _owner,
        address _claimSigner,
        address _moderator,
        uint256 _ratePerSecond
    ) {
        if (_nftContract == address(0)) revert ZeroAddress();
        if (_rewardToken == address(0)) revert ZeroAddress();
        if (_treasury == address(0)) revert ZeroAddress();
        if (_owner == address(0)) revert ZeroAddress();
        if (_claimSigner == address(0)) revert ZeroAddress();

        nftContract = IERC721(_nftContract);
        rewardToken = _rewardToken;
        treasury = _treasury;
        claimSigner = _claimSigner;
        moderator = _moderator;
        ratePerSecond = _ratePerSecond;
        claimsEnabled = true;

        _initializeOwner(_owner);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Checkpoints
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @dev Finalizes pending NFT-seconds for a user and updates their checkpoint
     * @param user Address to checkpoint
     */
    function _checkpoint(address user) internal {
        uint48 last = lastCheckpoint[user];
        uint256 count = _stakedTokens[user].length();
        if (last != 0 && count > 0) {
            uint256 elapsed = block.timestamp - last;
            accruedNFTSeconds[user] += elapsed * count;
        }
        lastCheckpoint[user] = uint48(block.timestamp);
    }

    /**
     * @notice Manually checkpoint a user's accrued NFT-seconds
     * @dev Useful for locking in accruals before a rate change
     * @param user Address to checkpoint
     */
    function checkpoint(address user) external {
        _checkpoint(user);
        emit Checkpointed(user, accruedNFTSeconds[user]);
    }

    /**
     * @notice Checkpoint multiple users in a single transaction
     * @param users Array of addresses to checkpoint
     */
    function checkpointBatch(address[] calldata users) external {
        uint256 len = users.length;
        for (uint256 i; i < len; ++i) {
            address user = users[i];
            _checkpoint(user);
            emit Checkpointed(user, accruedNFTSeconds[user]);
        }
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Staking
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @notice Stake a single NFT
     * @dev Caller must own the token and have approved this contract
     * @param tokenId Token ID to stake
     */
    function stake(uint256 tokenId) external nonReentrant whenNotPaused {
        _stake(msg.sender, tokenId);
    }

    /**
     * @notice Stake multiple NFTs in a single transaction
     * @dev Caller must own all tokens and have approved this contract
     * @param tokenIds Array of token IDs to stake
     */
    function stakeBatch(
        uint256[] calldata tokenIds
    ) external nonReentrant whenNotPaused {
        address staker = msg.sender;
        _checkpoint(staker);

        IERC721 nft = nftContract;
        uint256 len = tokenIds.length;
        uint48 ts = uint48(block.timestamp);

        for (uint256 i; i < len; ++i) {
            uint256 tokenId = tokenIds[i];
            if (nft.ownerOf(tokenId) != staker) revert NotTokenOwner();

            nft.transferFrom(staker, address(this), tokenId);
            stakes[tokenId] = StakeInfo({owner: staker, stakedAt: ts});

            if (!_stakedTokens[staker].add(tokenId))
                revert TokenAlreadyStaked();

            emit Staked(staker, tokenId, ts);
            emit Locked(tokenId);
        }

        totalStaked += len;
    }

    /**
     * @notice Unstake a single NFT
     * @dev Returns NFT to the staker, preserves accrued NFT-seconds
     * @param tokenId Token ID to unstake
     */
    function unstake(uint256 tokenId) external nonReentrant {
        _unstake(msg.sender, tokenId);
    }

    /**
     * @notice Unstake multiple NFTs in a single transaction
     * @param tokenIds Array of token IDs to unstake
     */
    function unstakeBatch(uint256[] calldata tokenIds) external nonReentrant {
        address staker = msg.sender;
        _checkpoint(staker);

        IERC721 nft = nftContract;
        uint256 len = tokenIds.length;
        uint256 nftSeconds = totalNFTSeconds(staker);

        for (uint256 i; i < len; ++i) {
            uint256 tokenId = tokenIds[i];
            StakeInfo storage info = stakes[tokenId];

            if (info.owner == address(0)) revert TokenNotStaked();
            if (info.owner != staker) revert NotStakeOwner();

            uint48 duration = uint48(block.timestamp - info.stakedAt);

            delete stakes[tokenId];

            if (!_stakedTokens[staker].remove(tokenId)) revert TokenNotInSet();

            nft.transferFrom(address(this), staker, tokenId);

            emit Unstaked(staker, tokenId, duration, nftSeconds);
            emit Unlocked(tokenId);
        }

        totalStaked -= len;
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Views
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @notice Returns the address that staked a specific token
     * @dev This is staking-specific, not standard ERC721 ownerOf
     * @param tokenId Token ID to query
     * @return Address of the staker, or zero if not staked
     */
    function stakerOf(uint256 tokenId) external view returns (address) {
        return stakes[tokenId].owner;
    }

    /**
     * @notice Returns all staked token IDs for an address
     * @param staker Address to query
     * @return Array of staked token IDs
     */
    function stakedTokensOf(
        address staker
    ) external view returns (uint256[] memory) {
        return _getStakedTokensArray(staker);
    }

    /**
     * @notice Returns the number of NFTs staked by an address
     * @param staker Address to query
     * @return Number of staked NFTs
     */
    function stakedBalanceOf(address staker) external view returns (uint256) {
        return _stakedTokens[staker].length();
    }

    /**
     * @notice Check if a token is currently staked
     * @param tokenId Token ID to check
     * @return True if staked
     */
    function isStaked(uint256 tokenId) external view returns (bool) {
        return stakes[tokenId].owner != address(0);
    }

    /**
     * @notice Returns how long a token has been staked
     * @param tokenId Token ID to query
     * @return Duration in seconds, or 0 if not staked
     */
    function currentStakeDuration(
        uint256 tokenId
    ) external view returns (uint48) {
        StakeInfo storage info = stakes[tokenId];
        if (info.owner == address(0)) return 0;
        return uint48(block.timestamp - info.stakedAt);
    }

    /**
     * @notice Returns stake info for a token
     * @param tokenId Token ID to query
     * @return staker Address of the staker
     * @return stakedAt Timestamp when staked
     */
    function getStakeInfo(
        uint256 tokenId
    ) external view returns (address staker, uint48 stakedAt) {
        StakeInfo storage info = stakes[tokenId];
        return (info.owner, info.stakedAt);
    }

    /**
     * @notice Returns total NFT-seconds (finalized + pending) for a user
     * @dev This is rate-independent; multiply by ratePerSecond for credits
     * @param user Address to query
     * @return Total NFT-seconds accrued
     */
    function totalNFTSeconds(address user) public view returns (uint256) {
        uint256 base = accruedNFTSeconds[user];
        uint48 last = lastCheckpoint[user];
        uint256 count = _stakedTokens[user].length();
        if (last == 0 || count == 0) return base;
        return base + (block.timestamp - last) * count;
    }

    /**
     * @notice Returns uncheckpointed NFT-seconds for a user
     * @param user Address to query
     * @return Pending NFT-seconds not yet finalized
     */
    function pendingNFTSeconds(address user) external view returns (uint256) {
        uint48 last = lastCheckpoint[user];
        uint256 count = _stakedTokens[user].length();
        if (last == 0 || count == 0) return 0;
        return (block.timestamp - last) * count;
    }

    /**
     * @notice Returns reward credits (NFT-seconds × ratePerSecond)
     * @dev Changes retroactively when ratePerSecond is updated
     * @param user Address to query
     * @return Reward credits in token wei
     */
    function rewardCredits(address user) public view returns (uint256) {
        return totalNFTSeconds(user) * ratePerSecond;
    }

    /**
     * @notice Alias for totalNFTSeconds for backward compatibility
     * @param user Address to query
     * @return Total NFT-seconds accrued
     */
    function totalAccruedTime(address user) external view returns (uint256) {
        return totalNFTSeconds(user);
    }

    /**
     * @notice Returns the reward token balance in the treasury
     * @return Treasury balance in token wei
     */
    function treasuryBalance() external view returns (uint256) {
        return IERC20(rewardToken).balanceOf(treasury);
    }

    /**
     * @notice Returns the treasury's allowance for this contract
     * @return Allowance in token wei
     */
    function treasuryAllowance() external view returns (uint256) {
        return IERC20(rewardToken).allowance(treasury, address(this));
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Claims
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @notice Claim reward tokens using a server-signed authorization
     * @dev Amount is cumulative; contract tracks already-claimed amounts
     * @param amount Cumulative amount authorized to claim
     * @param deadline Timestamp after which signature expires
     * @param nonce Expected nonce for replay protection
     * @param signature EIP-712 signature from claimSigner
     */
    function claim(
        uint256 amount,
        uint256 deadline,
        uint256 nonce,
        bytes calldata signature
    ) external nonReentrant {
        if (!claimsEnabled) revert ClaimsNotEnabled();
        if (block.timestamp > deadline) revert SignatureExpired();
        if (nonce != nonces[msg.sender]) revert InvalidNonce();

        uint256 alreadyClaimed = claimedAmount[msg.sender];
        if (amount <= alreadyClaimed) revert NothingToClaim();

        bytes32 digest = _hashTypedData(
            keccak256(
                abi.encode(CLAIM_TYPEHASH, msg.sender, amount, deadline, nonce)
            )
        );
        if (
            !SignatureCheckerLib.isValidSignatureNowCalldata(
                claimSigner,
                digest,
                signature
            )
        ) {
            revert InvalidSignature();
        }

        uint256 toClaim = amount - alreadyClaimed;
        nonces[msg.sender] = nonce + 1;
        claimedAmount[msg.sender] = amount;

        rewardToken.safeTransferFrom(treasury, msg.sender, toClaim);
        emit Claimed(msg.sender, toClaim, amount);
    }

    /**
     * @notice Returns the current nonce for a user
     * @param user Address to query
     * @return Current nonce
     */
    function getNonce(address user) external view returns (uint256) {
        return nonces[user];
    }

    /**
     * @notice Returns cumulative claimed amount for a user
     * @param user Address to query
     * @return Total amount claimed
     */
    function getClaimedAmount(address user) external view returns (uint256) {
        return claimedAmount[user];
    }

    /**
     * @notice Alias for totalNFTSeconds
     * @param user Address to query
     * @return Total NFT-seconds accrued
     */
    function getAccruedTime(address user) external view returns (uint256) {
        return totalNFTSeconds(user);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Admin
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @notice Update the claim signer address
     * @param _claimSigner New signer address
     */
    function setClaimSigner(address _claimSigner) external onlyOwner {
        if (_claimSigner == address(0)) revert ZeroAddress();
        emit SignerUpdated(claimSigner, _claimSigner);
        claimSigner = _claimSigner;
    }

    /**
     * @notice Update the moderator address
     * @param _moderator New moderator address (can be zero to disable)
     */
    function setModerator(address _moderator) external onlyOwner {
        emit ModeratorUpdated(moderator, _moderator);
        moderator = _moderator;
    }

    /**
     * @notice Update the treasury address
     * @param _treasury New treasury address
     */
    function setTreasury(address _treasury) external onlyOwner {
        if (_treasury == address(0)) revert ZeroAddress();
        emit TreasuryUpdated(treasury, _treasury);
        treasury = _treasury;
    }

    /**
     * @notice Update the emission rate
     * @dev Affects rewardCredits() retroactively for all users
     * @param _ratePerSecond New rate per NFT-second
     */
    function setRatePerSecond(uint256 _ratePerSecond) external onlyOwner {
        emit RateUpdated(ratePerSecond, _ratePerSecond);
        ratePerSecond = _ratePerSecond;
    }

    /**
     * @notice Enable or disable claims
     * @param _enabled Whether claims should be enabled
     */
    function setClaimsEnabled(bool _enabled) external onlyOwner {
        claimsEnabled = _enabled;
        emit ClaimsEnabledUpdated(_enabled, msg.sender);
    }

    /**
     * @notice Pause staking operations
     */
    function pause() external onlyOwner {
        paused = true;
        emit PausedStateChanged(true, msg.sender);
    }

    /**
     * @notice Unpause staking operations
     */
    function unpause() external onlyOwner {
        paused = false;
        emit PausedStateChanged(false, msg.sender);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Emergency
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @notice Emergency withdraw a single staked NFT back to its owner
     * @dev Only callable by owner or moderator. Preserves accrued NFT-seconds.
     * @param tokenId Token ID to withdraw
     */
    function emergencyWithdrawNFT(
        uint256 tokenId
    ) external onlyOwnerOrModerator nonReentrant {
        StakeInfo storage info = stakes[tokenId];
        address originalOwner = info.owner;

        if (originalOwner == address(0)) revert TokenNotStaked();

        _checkpoint(originalOwner);

        delete stakes[tokenId];

        if (!_stakedTokens[originalOwner].remove(tokenId))
            revert TokenNotInSet();

        --totalStaked;

        nftContract.transferFrom(address(this), originalOwner, tokenId);

        emit EmergencyNFTWithdraw(tokenId, originalOwner, msg.sender);
        emit Unlocked(tokenId);
    }

    /**
     * @notice Emergency withdraw multiple staked NFTs back to their owners
     * @param tokenIds Array of token IDs to withdraw
     */
    function emergencyWithdrawNFTBatch(
        uint256[] calldata tokenIds
    ) external onlyOwnerOrModerator nonReentrant {
        IERC721 nft = nftContract;
        uint256 len = tokenIds.length;

        for (uint256 i; i < len; ++i) {
            uint256 tokenId = tokenIds[i];
            StakeInfo storage info = stakes[tokenId];
            address originalOwner = info.owner;

            if (originalOwner == address(0)) revert TokenNotStaked();

            _checkpoint(originalOwner);

            delete stakes[tokenId];

            if (!_stakedTokens[originalOwner].remove(tokenId))
                revert TokenNotInSet();

            --totalStaked;

            nft.transferFrom(address(this), originalOwner, tokenId);
            emit EmergencyNFTWithdraw(tokenId, originalOwner, msg.sender);
            emit Unlocked(tokenId);
        }
    }

    /**
     * @notice Rescue an NFT sent directly via safeTransfer (not stake())
     * @dev Permissionless - returns NFT to recorded depositor
     * @param tokenId Token ID to rescue
     */
    function rescueUntrackedNFT(uint256 tokenId) external nonReentrant {
        if (stakes[tokenId].owner != address(0)) revert TokenAlreadyTracked();
        if (nftContract.ownerOf(tokenId) != address(this))
            revert TokenNotHeld();

        address depositor = untrackedDepositor[tokenId];
        if (depositor == address(0)) revert ZeroAddress();

        delete untrackedDepositor[tokenId];
        nftContract.transferFrom(address(this), depositor, tokenId);
        emit NFTRescued(tokenId, depositor, msg.sender);
    }

    /**
     * @notice Admin rescue for NFTs without a recorded depositor
     * @dev Fallback when permissionless rescue is not possible
     * @param tokenId Token ID to rescue
     * @param to Destination address
     */
    function rescueUntrackedNFTAdmin(
        uint256 tokenId,
        address to
    ) external onlyOwnerOrModerator nonReentrant {
        if (to == address(0)) revert ZeroAddress();
        if (stakes[tokenId].owner != address(0)) revert TokenAlreadyTracked();
        if (nftContract.ownerOf(tokenId) != address(this))
            revert TokenNotHeld();

        delete untrackedDepositor[tokenId];
        nftContract.transferFrom(address(this), to, tokenId);
        emit NFTRescued(tokenId, to, msg.sender);
    }

    /**
     * @notice Withdraw accidentally sent ERC20 tokens (not reward token)
     * @param token Token address to withdraw
     * @param amount Amount to withdraw
     */
    function emergencyWithdrawTokens(
        address token,
        uint256 amount
    ) external onlyOwner {
        if (token == rewardToken) revert CannotWithdrawRewardToken();
        token.safeTransfer(owner(), amount);
        emit EmergencyTokenWithdraw(token, amount, owner(), msg.sender);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // Internal
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * @dev Converts EnumerableSet to memory array
     */
    function _getStakedTokensArray(
        address staker
    ) internal view returns (uint256[] memory result) {
        EnumerableSet.UintSet storage tokens = _stakedTokens[staker];
        uint256 len = tokens.length();
        result = new uint256[](len);
        for (uint256 i; i < len; ++i) {
            result[i] = tokens.at(i);
        }
    }

    /**
     * @dev Internal stake logic
     */
    function _stake(address staker, uint256 tokenId) internal {
        _checkpoint(staker);

        IERC721 nft = nftContract;
        if (nft.ownerOf(tokenId) != staker) revert NotTokenOwner();

        nft.transferFrom(staker, address(this), tokenId);
        stakes[tokenId] = StakeInfo({
            owner: staker,
            stakedAt: uint48(block.timestamp)
        });

        if (!_stakedTokens[staker].add(tokenId)) revert TokenAlreadyStaked();
        ++totalStaked;

        emit Staked(staker, tokenId, uint48(block.timestamp));
        emit Locked(tokenId);
    }

    /**
     * @dev Internal unstake logic
     */
    function _unstake(address staker, uint256 tokenId) internal {
        _checkpoint(staker);

        StakeInfo storage info = stakes[tokenId];
        if (info.owner == address(0)) revert TokenNotStaked();
        if (info.owner != staker) revert NotStakeOwner();

        uint48 duration = uint48(block.timestamp - info.stakedAt);
        delete stakes[tokenId];

        if (!_stakedTokens[staker].remove(tokenId)) revert TokenNotInSet();
        --totalStaked;

        nftContract.transferFrom(address(this), staker, tokenId);
        emit Unstaked(staker, tokenId, duration, totalNFTSeconds(staker));
        emit Unlocked(tokenId);
    }

    /**
     * @dev Returns EIP-712 domain name and version
     */
    function _domainNameAndVersion()
        internal
        pure
        override
        returns (string memory name, string memory version)
    {
        return ("BearishHibearnation", "1");
    }

    /**
     * @notice ERC721 receiver hook
     * @dev Records depositor for NFTs sent via safeTransfer for rescue
     */
    function onERC721Received(
        address,
        address from,
        uint256 tokenId,
        bytes calldata
    ) external override returns (bytes4) {
        if (msg.sender != address(nftContract)) revert InvalidNFTContract();
        if (paused) revert Paused();

        if (from != address(0) && stakes[tokenId].owner == address(0)) {
            untrackedDepositor[tokenId] = from;
        }

        return this.onERC721Received.selector;
    }
}

File 2 of 13 : IHibearnation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

/**
 * @title IHibearnation
 * @author @bearish_af
 * @notice Interface for the BearishHibearnation NFT staking contract
 * @dev Defines all external functions, events, errors, and structs for the staking system
 */
interface IHibearnation is IERC721Receiver {
    struct StakeInfo {
        address owner;
        uint48 stakedAt;
    }

    event Staked(
        address indexed staker,
        uint256 indexed tokenId,
        uint48 timestamp
    );
    event Unstaked(
        address indexed staker,
        uint256 indexed tokenId,
        uint48 stakedDuration,
        uint256 totalNFTSeconds
    );
    event Locked(uint256 tokenId);
    event Unlocked(uint256 tokenId);
    event Claimed(
        address indexed user,
        uint256 amountClaimed,
        uint256 totalClaimed
    );
    event Checkpointed(address indexed user, uint256 accruedNFTSeconds);
    event EmergencyNFTWithdraw(
        uint256 indexed tokenId,
        address indexed to,
        address indexed by
    );
    event NFTRescued(
        uint256 indexed tokenId,
        address indexed to,
        address indexed by
    );
    event EmergencyTokenWithdraw(
        address indexed token,
        uint256 amount,
        address indexed to,
        address indexed by
    );
    event SignerUpdated(address indexed oldSigner, address indexed newSigner);
    event ModeratorUpdated(
        address indexed oldModerator,
        address indexed newModerator
    );
    event TreasuryUpdated(
        address indexed oldTreasury,
        address indexed newTreasury
    );
    event RateUpdated(uint256 oldRate, uint256 newRate);
    event ClaimsEnabledUpdated(bool enabled, address indexed by);
    event PausedStateChanged(bool paused, address indexed by);

    error ZeroAddress();
    error NotTokenOwner();
    error TokenNotStaked();
    error NotStakeOwner();
    error TokenAlreadyStaked();
    error TokenNotInSet();
    error TokenAlreadyTracked();
    error TokenNotHeld();
    error CannotWithdrawRewardToken();
    error InvalidSignature();
    error SignatureExpired();
    error InvalidNonce();
    error NothingToClaim();
    error ClaimsNotEnabled();
    error Paused();
    error InvalidNFTContract();

    function CLAIM_TYPEHASH() external view returns (bytes32);

    function DEFAULT_RATE_PER_SECOND() external view returns (uint256);

    function DN404_UNIT() external view returns (uint256);

    function nftContract() external view returns (IERC721);

    function rewardToken() external view returns (address);

    function treasury() external view returns (address);

    function claimSigner() external view returns (address);

    function moderator() external view returns (address);

    function ratePerSecond() external view returns (uint256);

    function paused() external view returns (bool);

    function claimsEnabled() external view returns (bool);

    function totalStaked() external view returns (uint256);

    function stakes(
        uint256 tokenId
    ) external view returns (address staker, uint48 stakedAt);

    function untrackedDepositor(
        uint256 tokenId
    ) external view returns (address);

    function accruedNFTSeconds(address user) external view returns (uint256);

    function lastCheckpoint(address user) external view returns (uint48);

    function claimedAmount(address user) external view returns (uint256);

    function nonces(address user) external view returns (uint256);

    function checkpoint(address user) external;

    function checkpointBatch(address[] calldata users) external;

    function stake(uint256 tokenId) external;

    function stakeBatch(uint256[] calldata tokenIds) external;

    function unstake(uint256 tokenId) external;

    function unstakeBatch(uint256[] calldata tokenIds) external;

    function stakerOf(uint256 tokenId) external view returns (address);

    function stakedTokensOf(
        address staker
    ) external view returns (uint256[] memory);

    function stakedBalanceOf(address staker) external view returns (uint256);

    function isStaked(uint256 tokenId) external view returns (bool);

    function currentStakeDuration(
        uint256 tokenId
    ) external view returns (uint48);

    function getStakeInfo(
        uint256 tokenId
    ) external view returns (address staker, uint48 stakedAt);

    function totalNFTSeconds(address user) external view returns (uint256);

    function pendingNFTSeconds(address user) external view returns (uint256);

    function rewardCredits(address user) external view returns (uint256);

    function totalAccruedTime(address user) external view returns (uint256);

    function treasuryBalance() external view returns (uint256);

    function treasuryAllowance() external view returns (uint256);

    function claim(
        uint256 amount,
        uint256 deadline,
        uint256 nonce,
        bytes calldata signature
    ) external;

    function getNonce(address user) external view returns (uint256);

    function getClaimedAmount(address user) external view returns (uint256);

    function getAccruedTime(address user) external view returns (uint256);

    function setClaimSigner(address _claimSigner) external;

    function setModerator(address _moderator) external;

    function setTreasury(address _treasury) external;

    function setRatePerSecond(uint256 _ratePerSecond) external;

    function setClaimsEnabled(bool _enabled) external;

    function pause() external;

    function unpause() external;

    function emergencyWithdrawNFT(uint256 tokenId) external;

    function emergencyWithdrawNFTBatch(uint256[] calldata tokenIds) external;

    function rescueUntrackedNFT(uint256 tokenId) external;

    function rescueUntrackedNFTAdmin(uint256 tokenId, address to) external;

    function emergencyWithdrawTokens(address token, uint256 amount) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    uint256 private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = uint256(uint160(address(this)));
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        // We will use `digest` to store the domain separator to save a bit of gas.
        if (_domainNameAndVersionMayChange()) {
            digest = _buildDomainSeparator();
        } else {
            digest = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, digest) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        // We will use `separator` to store the name hash to save a bit of gas.
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            separator = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            separator = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), separator) // Name hash.
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        uint256 cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Signature verification helper that supports both ECDSA signatures from EOAs
/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)
///
/// @dev Note:
/// - The signature checking functions use the ecrecover precompile (0x1).
/// - The `bytes memory signature` variants use the identity precompile (0x4)
///   to copy memory internally.
/// - Unlike ECDSA signatures, contract signatures are revocable.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               SIGNATURE CHECKING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    switch mload(signature)
                    case 64 {
                        let vs := mload(add(signature, 0x40))
                        mstore(0x20, add(shr(255, vs), 27)) // `v`.
                        mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    }
                    case 65 {
                        mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                        mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    }
                    default { break }
                    mstore(0x00, hash)
                    mstore(0x40, mload(add(signature, 0x20))) // `r`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }
                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                // Copy the `signature` over.
                let n := add(0x20, mload(signature))
                let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
                isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
                isValid := and(eq(mload(d), f), and(isValid, copied))
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    switch signature.length
                    case 64 {
                        let vs := calldataload(add(signature.offset, 0x20))
                        mstore(0x20, add(shr(255, vs), 27)) // `v`.
                        mstore(0x40, calldataload(signature.offset)) // `r`.
                        mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    }
                    case 65 {
                        mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                        calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
                    }
                    default { break }
                    mstore(0x00, hash)
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }
                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), signature.length)
                // Copy the `signature` over.
                calldatacopy(add(m, 0x64), signature.offset, signature.length)
                isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    mstore(0x00, hash)
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, r) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }
                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.
                mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
                isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
    /// If `signer.code.length == 0`, then validate with `ecrecover`, else
    /// it will validate with ERC1271 on `signer`.
    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        if (signer == address(0)) return isValid;
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            for {} 1 {} {
                if iszero(extcodesize(signer)) {
                    mstore(0x00, hash)
                    mstore(0x20, and(v, 0xff)) // `v`.
                    mstore(0x40, r) // `r`.
                    mstore(0x60, s) // `s`.
                    let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                    isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }
                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), s) // `s`.
                mstore8(add(m, 0xa4), v) // `v`.
                isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
                isValid := and(eq(mload(d), f), isValid)
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     ERC1271 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: These ERC1271 operations do NOT have an ECDSA fallback.

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            // Copy the `signature` over.
            let n := add(0x20, mload(signature))
            let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n)
            isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20)
            isValid := and(eq(mload(d), f), and(isValid, copied))
        }
    }

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNowCalldata(
        address signer,
        bytes32 hash,
        bytes calldata signature
    ) internal view returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), signature.length)
            // Copy the `signature` over.
            calldatacopy(add(m, 0x64), signature.offset, signature.length)
            isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.
            mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
            isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), s) // `s`.
            mstore8(add(m, 0xa4), v) // `v`.
            isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20)
            isValid := and(eq(mload(d), f), isValid)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     ERC6492 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: These ERC6492 operations now include an ECDSA fallback at the very end.
    // The calldata variants are excluded for brevity.

    /// @dev Returns whether `signature` is valid for `hash`.
    /// If the signature is postfixed with the ERC6492 magic number, it will attempt to
    /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check.
    /// Note: This function is NOT reentrancy safe.
    /// The verifier must be deployed.
    /// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
    /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04
    /// With a dedicated verifier, this function is safe to use in contracts
    /// that have been granted special permissions.
    function isValidERC6492SignatureNowAllowSideEffects(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
                let m_ := mload(0x40)
                let f_ := shl(224, 0x1626ba7e)
                mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m_, 0x04), hash_)
                let d_ := add(m_, 0x24)
                mstore(d_, 0x40) // The offset of the `signature` in the calldata.
                let n_ := add(0x20, mload(signature_))
                let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
                _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
                _isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
            }
            let noCode := iszero(extcodesize(signer))
            let n := mload(signature)
            for {} 1 {} {
                if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
                    if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
                    break
                }
                if iszero(noCode) {
                    let o := add(signature, 0x20) // Signature bytes.
                    isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
                    if isValid { break }
                }
                let m := mload(0x40)
                mstore(m, signer)
                mstore(add(m, 0x20), hash)
                pop(
                    call(
                        gas(), // Remaining gas.
                        0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Non-reverting verifier.
                        0, // Send zero ETH.
                        m, // Start of memory.
                        add(returndatasize(), 0x40), // Length of calldata in memory.
                        staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
                        0x00 // Length of returndata to write.
                    )
                )
                isValid := returndatasize()
                break
            }
            // Do `ecrecover` fallback if `noCode && !isValid`.
            for {} gt(noCode, isValid) {} {
                switch n
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { break }
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `hash`.
    /// If the signature is postfixed with the ERC6492 magic number, it will attempt
    /// to use a reverting verifier to deploy / prepare the `signer` smart account
    /// and do a `isValidSignature` check via the reverting verifier.
    /// Note: This function is reentrancy safe.
    /// The reverting verifier must be deployed.
    /// Otherwise, the function will return false if `signer` is not yet deployed / prepared.
    /// See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad
    function isValidERC6492SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            function callIsValidSignature(signer_, hash_, signature_) -> _isValid {
                let m_ := mload(0x40)
                let f_ := shl(224, 0x1626ba7e)
                mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m_, 0x04), hash_)
                let d_ := add(m_, 0x24)
                mstore(d_, 0x40) // The offset of the `signature` in the calldata.
                let n_ := add(0x20, mload(signature_))
                let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)
                _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20)
                _isValid := and(eq(mload(d_), f_), and(_isValid, copied_))
            }
            let noCode := iszero(extcodesize(signer))
            let n := mload(signature)
            for {} 1 {} {
                if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) {
                    if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) }
                    break
                }
                if iszero(noCode) {
                    let o := add(signature, 0x20) // Signature bytes.
                    isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40))))
                    if isValid { break }
                }
                let m := mload(0x40)
                mstore(m, signer)
                mstore(add(m, 0x20), hash)
                let willBeZeroIfRevertingVerifierExists :=
                    call(
                        gas(), // Remaining gas.
                        0x00007bd799e4A591FeA53f8A8a3E9f931626Ba7e, // Reverting verifier.
                        0, // Send zero ETH.
                        m, // Start of memory.
                        add(returndatasize(), 0x40), // Length of calldata in memory.
                        staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1.
                        0x00 // Length of returndata to write.
                    )
                isValid := gt(returndatasize(), willBeZeroIfRevertingVerifierExists)
                break
            }
            // Do `ecrecover` fallback if `noCode && !isValid`.
            for {} gt(noCode, isValid) {} {
                switch n
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { break }
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                isValid := gt(returndatasize(), shl(96, xor(signer, recovered)))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 6 of 13 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Reentrancy guard mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unauthorized reentrant call.
    error Reentrancy();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`.
    /// 9 bytes is large enough to avoid collisions with lower slots,
    /// but not too large to result in excessive bytecode bloat.
    uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      REENTRANCY GUARD                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Guards a function from reentrancy.
    modifier nonReentrant() virtual {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
                mstore(0x00, 0xab143c06) // `Reentrancy()`.
                revert(0x1c, 0x04)
            }
            sstore(_REENTRANCY_GUARD_SLOT, address())
        }
        _;
        /// @solidity memory-safe-assembly
        assembly {
            sstore(_REENTRANCY_GUARD_SLOT, codesize())
        }
    }

    /// @dev Guards a view function from read-only reentrancy.
    modifier nonReadReentrant() virtual {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
                mstore(0x00, 0xab143c06) // `Reentrancy()`.
                revert(0x1c, 0x04)
            }
        }
        _;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

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

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

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

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

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

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

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721
     * 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 address zero.
     *
     * 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);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {SingleUseETHVault} from "./SingleUseETHVault.sol";

/// @notice Library for force safe transferring ETH and ERC20s in ZKsync.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SafeTransferLib.sol)
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A single use ETH vault has been created for `to`, with `amount`.
    event SingleUseETHVaultCreated(address indexed to, uint256 amount, address vault);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /// @dev The ERC20 `totalSupply` query has failed.
    error TotalSupplyQueryFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 1000000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (address vault)
    {
        if (amount == uint256(0)) return address(0); // Early return if `amount` is zero.
        uint256 selfBalanceBefore = address(this).balance;
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfBalanceBefore, amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            pop(call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00))
        }
        if (address(this).balance == selfBalanceBefore) {
            vault = address(new SingleUseETHVault());
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x00, shr(96, shl(96, to)))
                if iszero(call(gas(), vault, amount, 0x00, 0x20, 0x00, 0x00)) { revert(0x00, 0x00) }
            }
            emit SingleUseETHVaultCreated(to, amount, vault);
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (address vault)
    {
        vault = forceSafeTransferETH(to, address(this).balance, gasStipend);
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferETH(address to, uint256 amount) internal returns (address vault) {
        vault = forceSafeTransferETH(to, amount, GAS_STIPEND_NO_GRIEF);
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    /// If force transfer is used, returns the vault. Else returns `address(0)`.
    function forceSafeTransferAllETH(address to) internal returns (address vault) {
        vault = forceSafeTransferETH(to, address(this).balance, GAS_STIPEND_NO_GRIEF);
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), 0x00, 0x00, 0x00, 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function trySafeTransferFrom(address token, address from, address to, uint256 amount)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                success := lt(or(iszero(extcodesize(token)), returndatasize()), success)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x34, 0) // Store 0 for the `amount`.
                    mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                    pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval.
                    mstore(0x34, amount) // Store back the original `amount`.
                    // Retry the approval, reverting upon failure.
                    success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    if iszero(and(eq(mload(0x00), 1), success)) {
                        // Check the `extcodesize` again just in case the token selfdestructs lol.
                        if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                            mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                            revert(0x1c, 0x04)
                        }
                    }
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul( // The arguments of `mul` are evaluated from right to left.
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }

    /// @dev Returns the total supply of the `token`.
    /// Reverts if the token does not exist or does not implement `totalSupply()`.
    function totalSupply(address token) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x18160ddd) // `totalSupply()`.
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20))
            ) {
                mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }
}

File 11 of 13 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC-721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC-721 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 12 of 13 : SingleUseETHVault.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice A single-use vault that allows a designated caller to withdraw all ETH in it.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SingleUseETHVault.sol)
contract SingleUseETHVault {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to withdraw all.
    error WithdrawAllFailed();

    /// @dev Not authorized.
    error Unauthorized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        WITHDRAW ALL                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    fallback() external payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x40, 0) // Optimization trick to remove free memory pointer initialization.
            let owner := sload(0)
            // Initialization.
            if iszero(owner) {
                sstore(0, calldataload(0x00)) // Store the owner.
                return(0x00, 0x00) // Early return.
            }
            // Authorization check.
            if iszero(eq(caller(), owner)) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
            let to := calldataload(0x00)
            // If the calldata is less than 32 bytes, zero-left-pad it to 32 bytes.
            // Then use the rightmost 20 bytes of the word as the `to` address.
            // This allows for the calldata to be `abi.encode(to)` or `abi.encodePacked(to)`.
            to := shr(mul(lt(calldatasize(), 0x20), shl(3, sub(0x20, calldatasize()))), to)
            // If `to` is `address(0)`, set it to `msg.sender`.
            to := xor(mul(xor(to, caller()), iszero(to)), to)
            // Transfers the whole balance to `to`.
            if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) {
                mstore(0x00, 0x651aee10) // `WithdrawAllFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "detectMissingLibraries": false,
  "forceEVMLA": false,
  "enableEraVMExtensions": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_nftContract","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_claimSigner","type":"address"},{"internalType":"address","name":"_moderator","type":"address"},{"internalType":"uint256","name":"_ratePerSecond","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"CannotWithdrawRewardToken","type":"error"},{"inputs":[],"name":"ClaimsNotEnabled","type":"error"},{"inputs":[],"name":"InvalidNFTContract","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotStakeOwner","type":"error"},{"inputs":[],"name":"NotTokenOwner","type":"error"},{"inputs":[],"name":"NothingToClaim","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"TokenAlreadyStaked","type":"error"},{"inputs":[],"name":"TokenAlreadyTracked","type":"error"},{"inputs":[],"name":"TokenNotHeld","type":"error"},{"inputs":[],"name":"TokenNotInSet","type":"error"},{"inputs":[],"name":"TokenNotStaked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"accruedNFTSeconds","type":"uint256"}],"name":"Checkpointed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountClaimed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalClaimed","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"ClaimsEnabledUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"EmergencyNFTWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"EmergencyTokenWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldModerator","type":"address"},{"indexed":true,"internalType":"address","name":"newModerator","type":"address"}],"name":"ModeratorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"NFTRescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"},{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"PausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"RateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":true,"internalType":"address","name":"newSigner","type":"address"}],"name":"SignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint48","name":"timestamp","type":"uint48"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint48","name":"stakedDuration","type":"uint48"},{"indexed":false,"internalType":"uint256","name":"totalNFTSeconds","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"CLAIM_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_RATE_PER_SECOND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DN404_UNIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accruedNFTSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"}],"name":"checkpointBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"currentStakeDuration","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"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":"emergencyWithdrawNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"emergencyWithdrawNFTBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyWithdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getAccruedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getClaimedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getStakeInfo","outputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint48","name":"stakedAt","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastCheckpoint","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"moderator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"pendingNFTSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratePerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"rescueUntrackedNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueUntrackedNFTAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rewardCredits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_claimSigner","type":"address"}],"name":"setClaimSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setClaimsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_moderator","type":"address"}],"name":"setModerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ratePerSecond","type":"uint256"}],"name":"setRatePerSecond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"stakedTokensOf","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint48","name":"stakedAt","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"totalAccruedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"totalNFTSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unstakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"untrackedDepositor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

9c4d535b000000000000000000000000000000000000000000000000000000000000000001000663e8b5975083e6cfd4f649a9d8282f41b682e9b9f3a2d1908d90ef928a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000516dc288e26b34557f68ea1c1ff13576eff8a1680000000000000000000000004b16703f7b0de03d23fd54606ed5786a59e3f27e000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a00000000000000000000000000000000000000000000000000001cd702e31894

Deployed Bytecode

0x0002000000000002001c000000000002000100000001035500000060031002700000059a0030019d0000059a0330019700000001002001900000001f0000c13d0000008002000039000000400020043f000000040030008c00000d140000413d000000000201043b000000e002200270000005aa0020009c000001190000a13d000005ab0020009c000001670000a13d000005ac0020009c000001e80000213d000005b80020009c000002d70000213d000005be0020009c000005890000213d000005c10020009c000007780000613d000005c20020009c00000d140000c13d000000240030008c0000085a0000813d00000d140000013d0000016004000039000000400040043f0000000002000416000000000002004b00000d140000c13d0000001f023000390000059b022001970000016002200039000000400020043f0000001f0530018f0000059c063001980000016002600039000000310000613d000000000701034f000000007807043c0000000004840436000000000024004b0000002d0000c13d000000000005004b0000003e0000613d000000000161034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000e00030008c00000d140000413d000001600200043d0000059d0020009c00000d140000213d000001800100043d000f00000001001d0000059d0010009c00000d140000213d000001a00100043d000e00000001001d0000059d0010009c00000d140000213d000001c00100043d000d00000001001d0000059d0010009c00000d140000213d000001e00100043d000c00000001001d0000059d0010009c00000d140000213d000002000100043d000b00000001001d0000059d0010009c00000d140000213d000a00000002001d000002200100043d000900000001001d0000000001000410000000800010043f0000059e01000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000401043b000000a00040043f000000400100043d000005a00010009c000011200000213d0000004002100039000000400020043f00000013020000390000000002210436000005a1030000410000000000320435000000400500043d000005a00050009c000011200000213d000600000004001d0000004003500039000000400030043f0000000103000039000800000005001d0000000004350436000005a203000041000700000004001d00000000003404350000059a0020009c0000059a02008041000000400220021000000000010104330000059a0010009c0000059a010080410000006001100210000000000121019f00000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f000005a3011001c700008010020000391663165e0000040f000000010020019000000d140000613d00000007020000290000059a0020009c0000059a020080410000004002200210000000080300002900000000030304330000059a0030009c0000059a030080410000006003300210000000000223019f000000000101043b000800000001001d00000000010004140000059a0010009c0000059a01008041000000c001100210000000000121019f000005a3011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000805000029000000c00050043f000000e00010043f000000400200043d0000008003200039000000000400041000000000004304350000006003200039000000060400002900000000004304350000004003200039000000000013043500000020012000390000000000510435000005a40100004100000000001204350000059a0020009c0000059a02008041000000400120021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000121019f000005a5011001c700008010020000391663165e0000040f00000001002001900000000a0200002900000d140000613d000000000101043b000001000010043f000000000002004b000008af0000613d0000000f0000006b000008af0000613d0000000e0000006b000008af0000613d0000000d0000006b000008af0000613d0000000c0000006b000008af0000613d0000000a01000029000001200010043f0000000f01000029000001400010043f000000000100041a000005a6011001970000000e011001af000000000010041b0000000103000039000000000103041a000005a6011001970000000c011001af000000000013041b0000000201000039000000000201041a000005a6022001970000000b022001af000000000021041b00000003030000390000000901000029000000000013041b0000000402000039000000000402041a0000065e0140019700000100011001bf000000000012041b000005a7010000410000000d06000029000000000061041b00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d02000039000005a8040000410000000005000019166316590000040f000000010020019000000d140000613d000000800100043d00000140000004430000016000100443000000a00100043d00000020020000390000018000200443000001a000100443000000c00100043d0000004003000039000001c000300443000001e0001004430000006001000039000000e00300043d000002000010044300000220003004430000008001000039000001000300043d00000240001004430000026000300443000000a001000039000001200300043d0000028000100443000002a000300443000000c001000039000001400300043d000002c000100443000002e000300443000001000020044300000007010000390000012000100443000005a901000041000016640001042e000005d80020009c0000019c0000213d000005ee0020009c000002770000a13d000005ef0020009c000003a00000213d000005f50020009c000006050000213d000005f80020009c000009600000613d000005f90020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000006060020009c00000d140000213d0000002304200039000000000034004b00000d140000813d0000000404200039000000000141034f000000000101043b000800000001001d000006060010009c00000d140000213d000700240020003d000000080100002900000005011002100000000701100029000000000031004b00000d140000213d000005a701000041000000000101041a0000059d011001970000000002000411000000000012004b000001480000613d0000000201000039000000000101041a0000059d01100197000000000012004b00000bc20000c13d0000061501000041000000000201041a0000000003000410000000000032004b000008000000613d000000000031041b0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000080000006b00000ea00000c13d0000000001000412001c00000001001d0000800201000039000000240300003900000000040004150000001c0440008a00000a490000013d000005c30020009c0000021f0000a13d000005c40020009c000002a60000213d000005ca0020009c000004250000213d000005cd0020009c000007880000613d000005ce0020009c00000d140000c13d000000440030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000f00000002001d0000059d0020009c00000d140000213d0000002401100370000000000301043b000005a701000041000000000201041a0000000001000411000000000021004b00000aee0000c13d000e00000003001d000d00000002001d0000060d01000041000000000010044300000000010004120000000400100443000000c001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000059d011001970000000f02000029000000000012004b00000cb40000c13d0000062b01000041000000000010043f0000062c010000410000166500010430000005d90020009c000002860000a13d000005da0020009c000003a90000213d000005e00020009c000006150000213d000005e30020009c000009720000613d000005e40020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000f00000001001d0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000f020000290000060802200198000000000101043b00000d220000613d000f00000002001d000000000101041a000e00000001001d000000000001004b0000000001000019000008960000613d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000f0210006c0000101b0000413d0000000001000019000008960000613d0000000e012000b900000000022100d90000000e0020006c000008960000613d0000101b0000013d000005ad0020009c000002e20000213d000005b30020009c000005980000213d000005b60020009c0000078d0000613d000005b70020009c00000d140000c13d000000240030008c00000d140000413d0000000401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d000005a701000041000000000101041a0000000002000411000000000012004b00000aee0000c13d00000603010000410000000c0010043f0000000f01000029000000000010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000611011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000d00000001001d000000000101041a000e00000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000e0010006c00000d240000a13d0000061201000041000000000010043f0000060f010000410000166500010430000005cf0020009c000003d00000a13d000005d00020009c000005740000213d000005d30020009c000007ae0000613d000005d40020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000301043b000005a701000041000000000101041a0000059d011001970000000002000411000000000012004b000002390000613d0000000201000039000000000101041a0000059d01100197000000000012004b00000bc20000c13d0000061501000041000000000201041a0000000004000410000000000042004b000008000000613d000000000041041b000f00000003001d000000000030043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000059d011001980000066c0000613d000e00000001001d166315090000040f0000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b0000000e01000029000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000f02000029166315990000040f000000000001004b000010170000c13d0000065601000041000000000010043f0000062c010000410000166500010430000005fa0020009c000003e70000a13d000005fb0020009c0000062e0000213d000005fe0020009c0000075e0000613d000005ff0020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d0000065c01000041000000800010043f0000060401000041000016640001042e000005e50020009c0000041a0000a13d000005e60020009c0000063e0000213d000005e90020009c000009a40000613d000005ea0020009c00000d140000c13d00000603010000410000000c0010043f0000000001000411000000000010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000611011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d0200003900000002030000390000064904000041000009e00000013d000005c50020009c0000057b0000213d000005c80020009c000007df0000613d000005c90020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d0000000f01000029166315090000040f0000000f01000029000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000000400200043d00000000001204350000059a0020009c0000059a02008041000000400120021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000002030000390000060c040000410000000f05000029000009e10000013d000005b90020009c000005ad0000213d000005bc0020009c0000075e0000613d000005bd0020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d00000001010000390000096d0000013d000005ae0020009c000005f20000213d000005b10020009c000007e60000613d000005b20020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000006060020009c00000d140000213d0000002304200039000000000034004b00000d140000813d0000000404200039000000000141034f000000000101043b000c00000001001d000006060010009c00000d140000213d000b00240020003d0000000c0100002900000005011002100000000b01100029000000000031004b00000d140000213d0000000c0000006b000009e40000613d000e00000000001d0000000e0100002900000005011002100000000b011000290000000101100367000000000101043b0000059d0010009c00000d140000213d0000059d01100197000f00000001001d000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000d00000001001d0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d020000290000060802200198000000000101043b000003580000613d000000000101041a000000000001004b000003580000613d000a00000002001d000d00000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000a0110006c0000000d030000290000101b0000413d00000000023100a9000003430000613d00000000011200d9000000000031004b0000101b0000c13d000d00000002001d0000000f01000029000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a0000000d03000029000000000032001a0000101b0000413d0000000002320019000000000021041b0000000f01000029000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000d00000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b00000608011001970000000d03000029000000000203041a0000060a02200197000000000112019f000000000013041b0000000f01000029000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000000400200043d00000000001204350000059a0020009c0000059a02008041000000400120021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000002030000390000060c040000410000000f05000029166316590000040f000000010020019000000d140000613d0000000e020000290000000102200039000e00000002001d0000000c0020006c000003030000413d000009e40000013d000005f00020009c000006470000213d000005f30020009c000009ba0000613d000005f40020009c00000d140000c13d000000240030008c0000085a0000813d00000d140000013d000005db0020009c000006700000213d000005de0020009c000009e60000613d000005df0020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b00000d140000c13d000005a702000041000000000502041a0000000002000411000000000052004b00000aee0000c13d0000000402000039000000000302041a0000065e03300197000000000001004b000001000330c1bf000000000032041b000000800010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000630011001c70000800d0200003900000002030000390000063604000041000009e10000013d000005d50020009c000007520000613d000005d60020009c000007730000613d000005d70020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d000005a701000041000000000501041a0000000001000411000000000051004b00000aee0000c13d0000000401000039000000000201041a0000065f0220019700000001022001bf000000000021041b0000000101000039000000800010043f0000000001000414000009b20000013d000006000020009c000008b30000613d000006010020009c000009030000613d000006020020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a0000059d002001980000000001000019000008960000613d000f00000002001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d0000000f02000029000000a002200270000000000101043b0000060803200197000000000013004b0000101b0000213d00000000012100490000060801100197000008960000013d000005eb0020009c000008ba0000613d000005ec0020009c000009160000613d000005ed0020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d00000002010000390000096d0000013d000005cb0020009c000007f40000613d000005cc0020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000301043b0000061501000041000000000201041a0000000004000410000000000042004b000008000000613d000000000041041b0000000401000039000000000101041a000000ff0010019000000bc60000c13d000f00000003001d0000000001000411166315090000040f0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000201043b000000400400043d000e00000004001d0000062001000041000000000014043500000004014000390000000f0300002900000000003104350000059a0040009c0000059a010000410000000001044019000000400110021000000000030004140000059a0030009c0000059a03008041000000c003300210000000000113019f00000621011001c70000059d02200197000d00000002001d1663165e0000040f0000000e0b00002900000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000004710000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000046d0000c13d000000000006004b0000047e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000d160000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006060010009c000011200000213d0000000100200190000011200000c13d000000400010043f000000200030008c00000d140000413d00000000010b04330000059d0010009c00000d140000213d0000000002000411000000000021004b0000123d0000c13d000006170100004100000000001004430000000d01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000000010004100000059d01100197000000240230003900000000001204350000061901000041000000000013043500000000010004110000059d01100197000000040230003900000000001204350000059a0030009c000e00000003001d0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000061a011001c70000000d02000029166316590000040f00000001002001900000125c0000613d0000000e01000029000006060010009c000011200000213d0000000e01000029000000400010043f0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000400200043d000e00000002001d000005a00020009c000011200000213d00000608021001970000000e030000290000004001300039000000400010043f00000000010004110000000001130436000c00000002001d000d00000001001d00000000002104350000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000e0200002900000000020204330000059d02200197000000000101043b000000000301041a0000062203300197000000000223019f0000000d030000290000000003030433000000a0033002100000062303300197000000000232019f000000000021041b0000000001000411000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000201043b0000000f01000029000000000010043f000e00000002001d0000000101200039000d00000001001d000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000000000001004b000012870000c13d0000000e01000029000000000101041a000b00000001001d000006060010009c000011200000213d0000000b0100002900000001011000390000000e02000029000000000012041b000000000020043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000b011000290000000f02000029000000000021041b0000000e01000029000000000101041a000e00000001001d000000000020043f0000000d01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000e02000029000000000021041b0000000701000039000000000201041a000000010220003a0000101b0000613d000000000021041b000000400100043d0000000c0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d020000390000000303000039000006240400004100000000050004110000000f06000029166316590000040f000000010020019000000d140000613d000000400100043d0000000f0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000001030000390000062504000041166316590000040f000000010020019000000d140000613d0000000001000412001500000001001d000080020100003900000024030000390000000004000415000000150440008a00000a490000013d000005d10020009c000008040000613d000005d20020009c00000d140000c13d000000240030008c000009050000813d00000d140000013d000005c60020009c000008090000613d000005c70020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000010043f0000000501000039000009690000013d000005bf0020009c000008580000613d000005c00020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d0000000001000412001400000001001d001300a00000003d000080050100003900000044030000390000000004000415000000140440008a000007f00000013d000005b40020009c000008630000613d000005b50020009c00000d140000c13d000000240030008c00000d140000413d0000000401100370000000000101043b0000059d0010009c00000d140000213d000005a702000041000000000202041a0000000003000411000000000023004b00000aee0000c13d000000000001004b00000d270000c13d0000060e01000041000000000010043f0000060f010000410000166500010430000005ba0020009c000008890000613d000005bb0020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000006060020009c00000d140000213d0000002304200039000000000034004b00000d140000813d0000000404200039000000000141034f000000000101043b000700000001001d000006060010009c00000d140000213d000600240020003d000000070100002900000005011002100000000601100029000000000031004b00000d140000213d0000061501000041000000000201041a0000000003000410000000000032004b000008000000613d000000000031041b0000000001000411166315090000040f0000000001000411166314af0000040f0000060d02000041000000000020044300000000020004120000000400200443000000a0020000390000002400200443000500000001001d00000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000070000006b00000d7d0000c13d0000000701000039000000000201041a000000070220006c0000101b0000413d000000000021041b0000000001000412001200000001001d000080020100003900000024030000390000000004000415000000120440008a00000a490000013d000005af0020009c0000089d0000613d000005b00020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d00000603020000410000000c0020043f000000000010043f0000000c010000390000002002000039000009110000013d000005f60020009c000009fa0000613d000005f70020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f00000008010000390000090e0000013d000005e10020009c00000a500000613d000005e20020009c00000d140000c13d000005a701000041000000000501041a0000000001000411000000000051004b00000aee0000c13d00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d020000390000000303000039000005a8040000410000000006000019166316590000040f000000010020019000000d140000613d000005a701000041000000000001041b0000000001000019000016640001042e000005fc0020009c00000a570000613d000005fd0020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f00000006010000390000090e0000013d000005e70020009c00000abd0000613d000005e80020009c00000d140000c13d0000000001000416000000000001004b00000d140000c13d000000000100041a0000096e0000013d000005f10020009c000007520000613d000005f20020009c00000d140000c13d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000301043b0000061501000041000000000201041a0000000004000410000000000042004b000008000000613d000000000041041b0000000001000411000f00000003001d166315090000040f0000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000301041a0000059d0130019800000be90000c13d0000065701000041000000000010043f0000062c010000410000166500010430000005dc0020009c00000ac80000613d000005dd0020009c00000d140000c13d000000440030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000e00000002001d0000002401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d000005a701000041000000000101041a0000059d011001970000000002000411000000000012004b0000068c0000613d0000000201000039000000000101041a0000059d01100197000000000012004b00000bc20000c13d0000061501000041000000000201041a0000000003000410000000000032004b000008000000613d000000000031041b0000000f0000006b000008af0000613d0000000e01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000059d0010019800000be50000c13d0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000201043b000000400400043d000d00000004001d0000062001000041000000000014043500000004014000390000000e0300002900000000003104350000059a0040009c0000059a010000410000000001044019000000400110021000000000030004140000059a0030009c0000059a03008041000000c003300210000000000113019f00000621011001c70000059d02200197000c00000002001d1663165e0000040f00000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d0b0000290000000d05700029000006d90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000006d50000c13d000000000006004b000006e60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000010d20000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006060010009c000011200000213d0000000100200190000011200000c13d000000400010043f000000200030008c00000d140000413d00000000010b04330000059d0010009c00000d140000213d0000000002000410000000000021004b000012410000c13d0000000e01000029000000000010043f0000000a01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a000005a602200197000000000021041b000006170100004100000000001004430000000c01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000e02000029000000000021043500000024013000390000000f0200002900000000002104350000061901000041000000000013043500000000010004100000059d01100197000000040230003900000000001204350000059a0030009c000d00000003001d0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000061a011001c70000000c02000029166316590000040f0000000100200190000012e40000613d0000000d01000029000006060010009c000011200000213d0000000d01000029000000400010043f00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d02000039000000040300003900000626040000410000000e050000290000000f060000290000000007000411166316590000040f000000010020019000000d140000613d0000000001000412001800000001001d000080020100003900000024030000390000000004000415000000180440008a00000a490000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f0000000c010000390000090e0000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000010043f0000000501000039000000200010043f00000040020000390000000001000019166316260000040f000000000101041a0000059d02100197000000800020043f000000a0011002700000060801100197000000a00010043f0000065d01000041000016640001042e0000000001000416000000000001004b00000d140000c13d0000000701000039000009120000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000010043f0000000501000039000000200010043f00000040020000390000000001000019166316260000040f000000000101041a0000059d0010019800000ac30000013d0000000001000416000000000001004b00000d140000c13d0000000301000039000009120000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000301043b000005a701000041000000000101041a0000000002000411000000000012004b00000aee0000c13d0000000301000039000000000101041a000000800010043f000f00000003001d000000a00030043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000613011001c70000800d0200003900000001030000390000061404000041166316590000040f000000010020019000000d140000613d0000000f010000290000000302000039000000000012041b0000000001000019000016640001042e0000000001000416000000000001004b00000d140000c13d0000001301000039000000800010043f000005a102000041000000a00020043f0000010003000039000000400030043f0000000103000039000000c00030043f000005a204000041000000e00040043f0000062e05000041000001000050043f000000e005000039000001200050043f000001e00010043f000002000020043f000002130000043f0000012001000039000001400010043f000002200030043f000002400040043f000002410000043f0000059e01000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000001600010043f0000000001000410000001800010043f000001a00000043f0000016001000039000001c00010043f000000600100043d000002600010043f000000000001004b00000bca0000c13d000001800100003900000bd40000013d0000000001000416000000000001004b00000d140000c13d0000061f01000041000000800010043f0000060401000041000016640001042e0000000001000416000000000001004b00000d140000c13d0000000001000412001100000001001d001000c00000003d000080050100003900000044030000390000000004000415000000110440008a00000005044002100000060d020000411663163b0000040f0000096e0000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000301043b0000061501000041000000000201041a0000000004000410000000000042004b00000af20000c13d0000065801000041000000000010043f0000060f0100004100001665000104300000000001000416000000000001004b00000d140000c13d000005a7010000410000096d0000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000701043b000000000807041a000006060080009c000011200000213d00000005018002100000003f021000390000061e02200197000000400300043d0000000002230019000e00000003001d000000000032004b00000000030000390000000103004039000006060020009c000011200000213d0000000100300190000011200000c13d000000400020043f0000000e0200002900000000068204360000001f0210018f000000000001004b0000083d0000613d0000000001160019000000000300003100000001033003670000000004060019000000003503043c0000000004540436000000000014004b000008390000c13d000000000002004b000000000008004b00000d2a0000c13d000000400100043d000000200200003900000000022104360000000e03000029000000000303043300000000003204350000004002100039000000000003004b0000084f0000613d0000000004000019000000006506043400000000025204360000000104400039000000000034004b0000084a0000413d00000000021200490000059a0020009c0000059a0200804100000060022002100000059a0010009c0000059a010080410000004001100210000000000112019f000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d166314af0000040f000008960000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d000005a701000041000000000101041a0000000002000411000000000012004b00000aee0000c13d0000000f06000029000000000006004b000008af0000613d000000000200041a00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c7000e00000002001d0000059d052001970000800d0200003900000003030000390000061004000041166316590000040f000000010020019000000d140000613d0000000e01000029000005a6011001970000000f011001af000000000010041b0000000001000019000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d166314af0000040f0000000302000039000000000202041a166314a10000040f000000400200043d00000000001204350000059a0020009c0000059a0200804100000040012002100000061d011001c7000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d000005a701000041000000000101041a0000000002000411000000000012004b00000aee0000c13d0000000f06000029000000000006004b00000c9e0000c13d0000063401000041000000000010043f0000062c0100004100001665000104300000000001000416000000000001004b00000d140000c13d0000000401000039000000000101041a0000ff000010019000000ac30000013d0000000001000416000000000001004b00000d140000c13d000000000100041a0000064d02000041000000800020043f0000059d01100197000000840010043f0000060d01000041000000000010044300000000010004120000000400100443000000c001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b00000000030004140000059d021001970000059a0030009c0000059a03008041000000c0013002100000064e011001c71663165e0000040f00000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000008e80000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000008e40000c13d000000000006004b000008f50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000009550000c13d0000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008fe0000c13d00000d6a0000013d000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f0000000b01000039000000200010043f00000040020000390000000001000019166316260000040f000000000101041a000000800010043f0000060401000041000016640001042e0000000001000416000000000001004b00000d140000c13d000000000100041a0000064b02000041000000800020043f0000059d01100197000000840010043f0000000001000410000000a40010043f0000060d01000041000000000010044300000000010004120000000400100443000000c001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b00000000030004140000059d021001970000059a0030009c0000059a03008041000000c0013002100000064c011001c71663165e0000040f00000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000009460000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000009420000c13d000000000006004b000009530000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000bd90000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c00000d140000413d000000800200043d000000000021043500000040011002100000061d011001c7000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000000000010043f0000000a01000039000000200010043f00000040020000390000000001000019166316260000040f000000000101041a0000059d01100197000000800010043f0000060401000041000016640001042e000000840030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000004402100370000000000202043b000d00000002001d0000002402100370000000000202043b000e00000002001d0000000402100370000000000202043b000c00000002001d0000006402100370000000000202043b000f00000002001d000006060020009c00000d140000213d0000000f020000290000002302200039000000000032004b00000d140000813d0000000f02000029000a00040020003d0000000a01100360000000000101043b000b00000001001d000006060010009c00000d140000213d0000000f010000290000002402100039000900000002001d0000000b01200029000000000031004b00000d140000213d0000061501000041000000000201041a0000000003000410000000000032004b000008000000613d000000000031041b0000000401000039000000000101041a0000ff000010019000000d4d0000c13d0000064801000041000000000010043f0000062c0100004100001665000104300000000001000416000000000001004b00000d140000c13d000005a701000041000000000501041a0000000001000411000000000051004b00000aee0000c13d0000000401000039000000000201041a0000065f02200197000000000021041b000000800000043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000630011001c70000800d0200003900000002030000390000063104000041000009e10000013d00000603010000410000000c0010043f0000000001000411000000000010043f0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000f00000001001d00000000010004140000059a0010009c0000059a01008041000000c00110021000000611011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000f02000029000006500220009a000000000021041b00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d02000039000000020300003900000651040000410000000005000411166316590000040f000000010020019000000d140000613d0000000001000019000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b0000059d0010009c00000d140000213d000000000010043f0000000901000039000000200010043f00000040020000390000000001000019166316260000040f000000000101041a0000060801100197000000800010043f0000060401000041000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b000006060020009c00000d140000213d0000002304200039000000000034004b00000d140000813d0000000404200039000000000141034f000000000101043b000800000001001d000006060010009c00000d140000213d000700240020003d000000080100002900000005011002100000000701100029000000000031004b00000d140000213d0000061501000041000000000201041a0000000003000410000000000032004b000008000000613d000000000031041b0000000401000039000000000101041a000000ff0010019000000bc60000c13d0000000001000411166315090000040f0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000f00000001001d0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000080000006b000011260000c13d0000000701000039000000000201041a000000080020002a0000101b0000413d0000000802200029000000000021041b0000000001000412001b00000001001d0000800201000039000000240300003900000000040004150000001b0440008a000000050440021000000617020000411663163b0000040f0000061502000041000000000012041b0000000001000019000016640001042e0000000001000416000000000001004b00000d140000c13d0000063701000041000000800010043f0000060401000041000016640001042e000000840030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000402100370000000000202043b0000059d0020009c00000d140000213d0000002402100370000000000202043b000f00000002001d0000059d0020009c00000d140000213d0000004402100370000000000202043b000e00000002001d0000006402100370000000000202043b000006060020009c00000d140000213d0000002304200039000000000034004b00000d140000813d0000000404200039000000000141034f000000000101043b000006060010009c00000d140000213d00000000011200190000002401100039000000000031004b00000d140000213d0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000059d011001970000000002000411000000000012004b000010210000c13d0000000401000039000000000101041a000000ff0010019000000bc60000c13d0000000f0000006b00000ab50000613d0000000e01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000059d0010019800000ab50000c13d0000000e01000029000000000010043f0000000a01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a000005a6022001970000000f022001af000000000021041b000000400100043d0000065b0200004100000000002104350000059a0010009c0000059a0100804100000040011002100000061d011001c7000016640001042e0000000001000416000000000001004b00000d140000c13d0000000401000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000060401000041000016640001042e000000240030008c00000d140000413d0000000002000416000000000002004b00000d140000c13d0000000401100370000000000101043b000f00000001001d0000059d0010009c00000d140000213d000005a701000041000000000101041a0000000002000411000000000012004b00000aee0000c13d0000000201000039000000000201041a00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c7000e00000002001d0000059d052001970000800d02000039000000030300003900000635040000410000000f06000029166316590000040f000000010020019000000d140000613d0000000e01000029000005a6011001970000000f011001af0000000202000039000000000012041b0000000001000019000016640001042e0000064a01000041000000000010043f0000060f010000410000166500010430000000000041041b000f00000003001d000000000030043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000059d0010019800000be50000c13d0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000201043b000000400400043d000e00000004001d0000062001000041000000000014043500000004014000390000000f0300002900000000003104350000059a0040009c0000059a010000410000000001044019000000400110021000000000030004140000059a0030009c0000059a03008041000000c003300210000000000113019f00000621011001c70000059d02200197000d00000002001d1663165e0000040f0000000e0b00002900000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900000b380000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000b340000c13d000000000006004b00000b450000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000d5f0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006060010009c000011200000213d0000000100200190000011200000c13d000000400010043f000000200030008c00000d140000413d00000000010b04330000059d0010009c00000d140000213d0000000002000410000000000021004b000012410000c13d0000000f01000029000000000010043f0000000a01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000e059d0010019c000008af0000613d0000000f01000029000000000010043f0000000a01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a000005a602200197000000000021041b000006170100004100000000001004430000000d01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000024013000390000000e0200002900000000002104350000061901000041000000000013043500000000010004100000059d01100197000000040230003900000000001204350000059a0030009c000c00000003001d0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000061a011001c70000000d02000029166316590000040f0000000100200190000012d70000613d0000000c01000029000006060010009c000011200000213d0000000c01000029000000400010043f00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d020000390000000403000039000000000700041100000626040000410000000f050000290000000e06000029166316590000040f000000010020019000000d140000613d0000000001000412001600000001001d000080020100003900000024030000390000000004000415000000160440008a00000a490000013d0000065401000041000000000010043f0000062c0100004100001665000104300000065a01000041000000000010043f0000062c0100004100001665000104300000028003000039000000000200001900000080050000390000000004030019000000005305043400000000033404360000000102200039000000000012004b00000bcd0000413d000000e00140008a0000059a0010009c0000059a0100804100000060011002100000062f011001c7000016640001042e0000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000be00000c13d00000d6a0000013d0000063201000041000000000010043f0000062c0100004100001665000104300000000002000411000000000021004b00000e9c0000c13d000e00000003001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d0000000e02000029000000a002200270000000000301043b000e00000002001d0000060801200197000d00000003001d000000000031004b0000101b0000213d0000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b0000000001000411000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000f02000029166315990000040f000000000001004b000002730000613d0000000701000039000000000201041a000000000002004b0000101b0000613d000000010220008a000000000021041b0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000006170200004100000000002004430000059d01100197000c00000001001d000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000000010004110000059d01100197000000240230003900000000001204350000061901000041000000000013043500000000010004100000059d01100197000000040230003900000000001204350000059a0030009c000b00000003001d0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000061a011001c70000000c02000029166316590000040f0000000100200190000012ca0000613d0000000b01000029000006060010009c000011200000213d0000000d020000290000000e0120006a000e06080010019b0000000b01000029000000400010043f0000000001000411166314af0000040f000000400200043d000000200320003900000000001304350000000e0100002900000000001204350000059a0020009c0000059a02008041000000400120021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f00000607011001c70000800d0200003900000003030000390000061b0400004100000000050004110000000f06000029166316590000040f000000010020019000000d140000613d000000400100043d0000000f0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000001030000390000061c04000041166316590000040f000000010020019000000d140000613d0000000001000412001a00000001001d0000800201000039000000240300003900000000040004150000001a0440008a00000a490000013d0000000101000039000000000201041a00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c7000e00000002001d0000059d052001970000800d0200003900000003030000390000060504000041166316590000040f000000010020019000000d140000613d0000000e01000029000005a6011001970000000f011001af0000000102000039000000000012041b0000000001000019000016640001042e000005a701000041000000000101041a000000140010043f0000000e01000029000000340010043f0000062701000041000000000010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000628011001c7166316590000040f00000060031002700000059a03300197000000200030008c000c00000003001d000000200400003900000000040340190000001f0340018f000000200740019000000cd00000613d000000000401034f0000000005000019000000004604043c0000000005650436000000000075004b00000ccc0000c13d000000000003004b00000cdd0000613d000000000171034f0000000303300210000000000407043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f0000000000170435000000000100043d000000010010008c00000000010000390000000101006039000b00000002001d000000000112016f000000010010019000000cfc0000c13d000006170100004100000000001004430000000f01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000010200008a0000000b0220014f000000000101043b000000000001004b000000000100003900000001010060390000000c001001b0000000010220c1bf0000000100200190000010250000c13d000000340000043f000005a701000041000000000201041a000000400100043d0000000e0300002900000000003104350000059a0010009c0000059a01008041000000400110021000000000030004140000059a0030009c0000059a03008041000000c003300210000000000113019f0000060b011001c70000059d062001970000800d0200003900000004030000390000062a040000410000000f050000290000000d07000029166316590000040f0000000100200190000009e40000c13d000000000100001900001665000104300000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000d1d0000c13d00000d6a0000013d0000000001000019000008960000013d0000000d01000029000000000001041b0000000f01000029166315830000040f0000000001000019000016640001042e0000000003000019000c00000006001d000d00000007001d000b00000008001d000000000107041a000000000031004b000010110000a13d000f00000003001d000000000070043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000e0200002900000000020204330000000f03000029000000000023004b0000000d07000029000010110000813d00000005023002100000000c060000290000000002620019000000000101043b0000000001310019000000000101041a000000000012043500000001033000390000000b0030006c00000d2e0000413d000008400000013d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000e0010006c000010290000a13d0000064701000041000000000010043f0000062c0100004100001665000104300000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000d660000c13d000000000005004b00000d770000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000059a0020009c0000059a020080410000004002200210000000000112019f0000166500010430000b059d0010019b00000000010004110004059d0010019b00000000010004100003059d0010019b0000000002000019000a00000002001d000000050120021000000006011000290000000101100367000000000101043b000f00000001001d000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a0000059d012001980000066c0000613d000e00000002001d0000000002000411000000000021004b00000e9c0000c13d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d0000000e02000029000000a002200270000000000301043b000900000002001d0000060801200197000800000003001d000000000031004b0000101b0000213d0000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b0000000001000411000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000201043b0000000f01000029000000000010043f000e00000002001d0000000101200039000c00000001001d000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000e03000029000000000101043b000000000101041a000000000001004b000002730000613d000000000203041a000000000002004b0000101b0000613d000000000021004b000d00000001001d00000e200000613d000200000002001d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d020000290001000100200092000000000101043b0000000e04000029000000000204041a000000010020006c000010110000a13d0000000202000029000000010220008a0000000001120019000000000101041a000200000001001d000000000040043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b00000001011000290000000202000029000000000021041b000000000020043f0000000c01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000d02000029000000000021041b0000000e03000029000000000103041a000d00000001001d000000000001004b000012560000613d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d02000029000000010220008a000000000101043b0000000001210019000000000001041b0000000e01000029000000000021041b0000000f01000029000000000010043f0000000c01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b000006170100004100000000001004430000000b01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000024013000390000000402000029000000000021043500000619010000410000000001130436000c00000001001d0000000401300039000000030200002900000000002104350000059a0030009c000e00000003001d0000059a010000410000000001034019000d00400010021800000000010004140000059a0010009c0000059a01008041000000c0011002100000000d011001af0000061a011001c70000000b02000029166316590000040f0000000100200190000012490000613d0000000e03000029000006060030009c000011200000213d0000000802000029000000090120006a0000060801100197000000400030043f00000005020000290000000c040000290000000000240435000000000013043500000000010004140000059a0010009c0000059a01008041000000c0011002100000000d011001af00000607011001c70000800d0200003900000003030000390000061b0400004100000000050004110000000f06000029166316590000040f000000010020019000000d140000613d000000400100043d0000000f0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000001030000390000061c04000041166316590000040f000000010020019000000d140000613d0000000a020000290000000102200039000000070020006c00000d830000413d000005e60000013d0000064f01000041000000000010043f0000062c010000410000166500010430000a059d0010019b00000000010004100006059d0010019b0000000002000019000900000002001d000000050120021000000007011000290000000101100367000000000101043b000f00000001001d000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000059d011001980000066c0000613d000e00000001001d000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a000d00000001001d0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d020000290000060802200198000000000101043b00000f070000613d000000000101041a000000000001004b00000f070000613d000c00000002001d000d00000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000c0110006c0000000d030000290000101b0000413d00000000023100a900000ef20000613d00000000011200d9000000000031004b0000101b0000c13d000d00000002001d0000000e01000029000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000201041a0000000d03000029000000000032001a0000101b0000413d0000000002320019000000000021041b0000000e01000029000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000d00000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b00000608011001970000000d03000029000000000203041a0000060a02200197000000000112019f000000000013041b0000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b0000000e01000029000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000201043b0000000f01000029000000000010043f000d00000002001d0000000101200039000b00000001001d000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d03000029000000000101043b000000000101041a000000000001004b000002730000613d000000000203041a000000000002004b0000101b0000613d000000000021004b000c00000001001d00000f980000613d000500000002001d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000c020000290004000100200092000000000101043b0000000d04000029000000000204041a000000040020006c000010110000a13d0000000502000029000000010220008a0000000001120019000000000101041a000500000001001d000000000040043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b00000004011000290000000502000029000000000021041b000000000020043f0000000b01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000c02000029000000000021041b0000000d03000029000000000103041a000c00000001001d000000000001004b000012560000613d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000c02000029000000010220008a000000000101043b0000000001210019000000000001041b0000000d01000029000000000021041b0000000f01000029000000000010043f0000000b01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000001041b0000000701000039000000000101041a000000000001004b0000101b0000613d000000010110008a0000000702000039000000000012041b000006170100004100000000001004430000000a01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000024013000390000000e020000290000000000210435000006190100004100000000001304350000000401300039000000060200002900000000002104350000059a0030009c000d00000003001d0000059a010000410000000001034019000c00400010021800000000010004140000059a0010009c0000059a01008041000000c0011002100000000c011001af0000061a011001c70000000a02000029166316590000040f00000001002001900000126d0000613d0000000d01000029000006060010009c000011200000213d0000000d01000029000000400010043f00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d0200003900000004030000390000062d040000410000000f050000290000000e060000290000000007000411166316590000040f000000010020019000000d140000613d0000000f010000290000000d02000029000000000012043500000000010004140000059a0010009c0000059a01008041000000c0011002100000000c011001af0000060b011001c70000800d0200003900000001030000390000061c04000041166316590000040f000000010020019000000d140000613d00000009020000290000000102200039000000080020006c00000ea40000413d000001600000013d0000065501000041000000000010043f0000003201000039000000040010043f000006210100004100001665000104300000000701000039000000000201041a000000000002004b000010de0000c13d0000065501000041000000000010043f0000001101000039000000040010043f000006210100004100001665000104300000065901000041000000000010043f0000062c0100004100001665000104300000062901000041000000000010043f0000060f0100004100001665000104300000000001000411000000000010043f0000000c01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0000000d0010006b000012450000c13d0000000b01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000000000101041a0008000c00100073000012690000a13d000000400100043d000000a0021000390000000d03000029000000000032043500000080021000390000000e03000029000000000032043500000060021000390000000c030000290000000000320435000000400210003900000000030004110000000000320435000000a0020000390000000002210436000006370300004100000000003204350000063a0010009c000011200000213d000000c003100039000000400030043f0000059a0020009c0000059a02008041000000400220021000000000010104330000059a0010009c0000059a010080410000006001100210000000000121019f00000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f000005a3011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000e00000001001d0000060d010000410000000000100443000000000100041200000004001004430000008001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000700000001001d0000060d01000041000000000010044300000000010004120000000400100443000000240000044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000600000001001d0000060d010000410000000000100443000000000100041200000004001004430000002001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000500000001001d0000059e01000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000400000001001d0000000001000410000000060010006c000013000000c13d0000000502000029000000040020006b000013000000c13d0000063b01000041000000000010043f00000007010000290000001a0010043f0000000e010000290000003a0010043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000063c011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000700000001001d0000003a0000043f0000000101000039000000000101041a000600000001001d000e059d0010019c000013400000c13d0000064601000041000000000010043f0000062c0100004100001665000104300000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000010d90000c13d00000d6a0000013d000000010220008a000000000021041b0000060d01000041000000000010044300000000010004120000000400100443000000a001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000006170200004100000000002004430000059d01100197000d00000001001d000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000024013000390000000e0200002900000000002104350000061901000041000000000013043500000000010004100000059d01100197000000040230003900000000001204350000059a0030009c000c00000003001d0000059a010000410000000001034019000b00400010021800000000010004140000059a0010009c0000059a01008041000000c0011002100000000b011001af0000061a011001c70000000d02000029166316590000040f00000001002001900000127a0000613d0000000c01000029000006060010009c000012a40000a13d0000065501000041000000000010043f0000004101000039000000040010043f000006210100004100001665000104300000000f02000029000b06080020019b000e059d0010019b00000000010004100006059d0010019b00000000010004110005059d0010019b0000000002000019000a00000002001d000000050120021000000007011000290000000101100367000000000201043b000000400300043d000d00000003001d000006200100004100000000001304350000000401300039000f00000002001d00000000002104350000059a0030009c0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f00000621011001c70000000e020000291663165e0000040f0000000d0a00002900000060031002700000059a03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011550000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011510000c13d0000001f07400190000011620000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f000000000065043500000001002001900000128b0000613d0000001f01400039000000600210018f0000000001a20019000000000021004b00000000020000390000000102004039000006060010009c000011200000213d0000000100200190000011200000c13d000000400010043f000000200030008c00000d140000413d00000000010a04330000059d0010009c00000d140000213d0000000002000411000000000021004b0000123d0000c13d000006170100004100000000001004430000000e01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b00000d140000613d000000400300043d00000044013000390000000f02000029000000000021043500000024013000390000000602000029000000000021043500000619010000410000000001130436000c00000001001d0000000401300039000000050200002900000000002104350000059a0030009c000d00000003001d0000059a010000410000000001034019000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000061a011001c70000000e02000029166316590000040f0000000100200190000012970000613d0000000d02000029000006060020009c000011200000213d000000400020043f000005a00020009c000011200000213d0000004001200039000000400010043f000000000100041100000000001204350000000b010000290000000c0200002900000000001204350000000f01000029000000000010043f0000000501000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d0200002900000000020204330000059d02200197000000000101043b000000000301041a0000062203300197000000000223019f0000000c030000290000000003030433000000a0033002100000062303300197000000000232019f000000000021041b0000000001000411000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000201043b0000000f01000029000000000010043f000d00000002001d0000000101200039000c00000001001d000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d02000029000000000101043b000000000101041a000000000001004b000012870000c13d000000000102041a000006060010009c000011200000213d000900000001001d0000000101100039000000000012041b000000000020043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b00000009011000290000000f02000029000000000021041b0000000d01000029000000000101041a000d00000001001d000000000020043f0000000c01000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000d02000029000000000021041b000000400100043d0000000b0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d020000390000000303000039000006240400004100000000050004110000000f06000029166316590000040f000000010020019000000d140000613d000000400100043d0000000f0200002900000000002104350000059a0010009c0000059a01008041000000400110021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f0000060b011001c70000800d0200003900000001030000390000062504000041166316590000040f000000010020019000000d140000613d0000000a020000290000000102200039000000080020006c0000112e0000413d00000a3d0000013d0000065201000041000000000010043f0000062c0100004100001665000104300000063301000041000000000010043f0000062c0100004100001665000104300000063801000041000000000010043f0000062c01000041000016650001043000000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012510000c13d000012f00000013d0000065501000041000000000010043f0000003101000039000000040010043f0000062101000041000016650001043000000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012640000c13d000012f00000013d0000063901000041000000000010043f0000062c01000041000016650001043000000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012750000c13d000012f00000013d00000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012820000c13d000012f00000013d0000065301000041000000000010043f0000062c0100004100001665000104300000001f0530018f0000059c06300198000000400200043d000000000462001900000d6a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000012920000c13d00000d6a0000013d00000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000129f0000c13d000012f00000013d0000000c01000029000000400010043f00000000010004140000059a0010009c0000059a01008041000000c001100210000005a3011001c70000800d0200003900000004030000390000062d040000410000000f050000290000000e060000290000000007000411166316590000040f000000010020019000000d140000613d0000000f010000290000000c02000029000000000012043500000000010004140000059a0010009c0000059a01008041000000c0011002100000000b011001af0000060b011001c70000800d0200003900000001030000390000061c04000041166316590000040f000000010020019000000d140000613d0000000001000412001700000001001d000080020100003900000024030000390000000004000415000000170440008a00000a490000013d00000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012d20000c13d000012f00000013d00000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012df0000c13d000012f00000013d00000060061002700000001f0460018f0000059c05600198000000400200043d0000000003520019000012f00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000012ec0000c13d0000059a06600197000000000004004b000012fe0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000130435000000600160021000000d780000013d000000400200043d000005a401000041000600000002001d0000000001120436000700000001001d0000060d010000410000000000100443000000000100041200000004001004430000004001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000070200002900000000001204350000060d010000410000000000100443000000000100041200000004001004430000006001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000101043b0000000604000029000000800240003900000000030004100000000000320435000000600240003900000004030000290000000000320435000000400240003900000000001204350000059a0040009c0000059a04008041000000400140021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000121019f000005a5011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b000700000001001d000010b70000013d000000400100043d000500000001001d000006170100004100000000001004430000000e01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000000101043b000000000001004b000013660000c13d0000000b01000029000000400010008c000013c10000613d0000000b01000029000000410010008c000010ce0000c13d0000000f0100002900000064011000390000000101100367000000000101043b000000f801100270000000200010043f000000090100002900000001011003670000004002000039000000001301043c0000000002320436000000800020008c000013610000c13d000013ce0000013d000000050500002900000064025000390000004401500039000000240650003900000004035000390000063d040000410000000000450435000000070400002900000000004304350000004003000039000f00000006001d00000000003604350000000b04000029000000000041043500000660034001980000001f0440018f0000000001320019000000090500002900000001055003670000137f0000613d000000000605034f000000006706043c0000000002720436000000000012004b0000137b0000c13d000000000004004b0000138c0000613d000000000235034f0000000303400210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f000000000021043500000005010000290000059a0010009c0000059a0100804100000040011002100000000b020000290000063e0020009c0000063e020080410000006002200210000000000112019f00000000020004140000059a0020009c0000059a02008041000000c002200210000000000121019f0000063f0110009a0000000e020000291663165e0000040f00000060031002700000059a03300197000000200030008c00000020030080390000001f0430018f00000020053001900000000f03500029000013ab0000613d000000000601034f0000000f07000029000000006806043c0000000007870436000000000037004b000013a70000c13d000000000004004b000013b80000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000f0100002900000000010104330000063d0010009c00000000010000390000000101006039000000000112016f0000000100100190000010ce0000613d000013fc0000013d0000000a0400002900000040014000390000000101100367000000000101043b000000ff031002700000001b03300039000000200030043f00000020034000390000000102300367000000000202043b000000400020043f0000064001100197000000600010043f0000000701000029000000000010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000641011001c700000001020000391663165e0000040f000000010900003900000060031002700000059a03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000013e60000613d000000000701034f000000007807043c0000000009890436000000000049004b000013e20000c13d000000010220018f000000000005004b000013f40000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000000001020433000000600000043f0000000502000029000000400020043f000000060110014f0000006001100210000000000013004b000010ce0000a13d0000000d01000029000000010010003a0000101b0000413d0000000001000411000000000010043f0000000c01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d0000000d020000290000000102200039000000000101043b000000000021041b0000000001000411000000000010043f0000000b01000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f000000010020019000000d140000613d000000000101043b0000000c02000029000000000021041b0000060d01000041000000000010044300000000010004120000000400100443000000c001000039000000240010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000616011001c700008005020000391663165e0000040f00000001002001900000149c0000613d000000000301043b000000400100043d000e00000001001d000000000100041a0000000802000029000000600020043f0000000002000411000000400020043f00000060011002100000002c0010043f00000642010000410000000c0010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000643011001c7000d00000003001d0000000002030019166316590000040f000f00000002001d00000060021002700000059a02200197000000200020008c000b00000002001d00000020020080390000001f0320018f0000002002200190000014520000613d000000000401034f0000000005000019000000004604043c0000000005650436000000000025004b0000144e0000c13d000000000003004b0000145f0000613d000000000121034f0000000303300210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f0000000000120435000000000100043d000000010010008c000000000100003900000001010060390000000f0110017f00000001001001900000147d0000c13d000006170100004100000000001004430000000d01000029000000040010044300000000010004140000059a0010009c0000059a01008041000000c00110021000000618011001c700008002020000391663165e0000040f00000001002001900000149c0000613d000000010200008a0000000f0220014f000000000101043b000000000001004b000000000100003900000001010060390000000b001001b0000000010220c1bf00000001002001900000149d0000c13d000000600000043f0000000e03000029000000400030043f00000020013000390000000c020000290000000000210435000000080100002900000000001304350000059a0030009c0000059a03008041000000400130021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f00000607011001c70000800d02000039000000020300003900000645040000410000000005000411166316590000040f000000010020019000000d140000613d0000000001000412001900000001001d000080020100003900000024030000390000000004000415000000190440008a00000a490000013d000000000001042f0000064401000041000000000010043f0000060f010000410000166500010430000000000301001900000000011200a9000000000003004b000014a80000613d00000000033100d9000000000023004b000014a90000c13d000000000001042d0000065501000041000000000010043f0000001101000039000000040010043f0000062101000041000016650001043000030000000000020000059d01100197000300000001001d000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000015000000613d000000000101043b000000000101041a000200000001001d0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000015000000613d000000000101043b000000000101041a000100000001001d0000000301000029000000000010043f0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000015000000613d00000001020000290000060802200198000000000101043b000014fe0000613d000000000101041a000000000001004b000014fe0000613d000100000002001d000300000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f0000000100200190000015080000613d000000000101043b000000010210006c00000002040000290000000305000029000015020000413d00000000035200a90000000001430019000014fb0000613d00000000022300d9000000000052004b000015020000c13d000000000041004b000015020000413d000000000001042d0000000201000029000000000001042d000000000100001900001665000104300000065501000041000000000010043f0000001101000039000000040010043f00000621010000410000166500010430000000000001042f00030000000000020000059d01100197000300000001001d000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f00000001002001900000157a0000613d000000000101043b000000000101041a000200000001001d0000000601000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f00000001002001900000157a0000613d00000002020000290000060802200198000000000101043b000015580000613d000000000101041a000000000001004b000015580000613d000100000002001d000200000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000157c0000613d000000000101043b000000010110006c00000002030000290000157d0000413d00000000023100a9000015430000613d00000000011200d9000000000031004b0000157d0000c13d000200000002001d0000000301000029000000000010043f0000000801000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f00000001002001900000157a0000613d000000000101043b000000000201041a0000000203000029000000000032001a0000157d0000413d0000000002320019000000000021041b0000000301000029000000000010043f0000000901000039000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f00000001002001900000157a0000613d000000000101043b000300000001001d0000060901000041000000000010044300000000010004140000059a0010009c0000059a01008041000000c0011002100000059f011001c70000800b020000391663165e0000040f00000001002001900000157c0000613d000000000101043b00000608011001970000000303000029000000000203041a0000060a02200197000000000112019f000000000013041b000000000001042d00000000010000190000166500010430000000000001042f0000065501000041000000000010043f0000001101000039000000040010043f000006210100004100001665000104300001000000000002000005a702000041000000000502041a00000000020004140000059d061001970000059a0020009c0000059a02008041000000c001200210000005a3011001c70000800d020000390000000303000039000005a804000041000100000006001d166316590000040f0000000100200190000015970000613d000005a7010000410000000102000029000000000021041b000000000001042d000000000100001900001665000104300006000000000002000300000002001d000000000020043f000600000001001d0000000101100039000400000001001d000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000016110000613d0000000603000029000000000101043b000000000101041a000000000001004b0000160f0000613d000000000203041a000000000002004b000016130000613d000000000021004b000500000001001d000015ed0000613d000200000002001d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f0000000100200190000016110000613d00000005020000290001000100200092000000000101043b0000000604000029000000000204041a000000010020006c000016190000a13d0000000202000029000000010220008a0000000001120019000000000101041a000200000001001d000000000040043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f0000000100200190000016110000613d000000000101043b00000001011000290000000202000029000000000021041b000000000020043f0000000401000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000016110000613d000000000101043b0000000502000029000000000021041b0000000603000029000000000103041a000500000001001d000000000001004b0000161f0000613d000000000030043f00000000010004140000059a0010009c0000059a01008041000000c0011002100000060b011001c700008010020000391663165e0000040f0000000100200190000016110000613d0000000502000029000000010220008a000000000101043b0000000001210019000000000001041b0000000601000029000000000021041b0000000301000029000000000010043f0000000401000029000000200010043f00000000010004140000059a0010009c0000059a01008041000000c00110021000000607011001c700008010020000391663165e0000040f0000000100200190000016110000613d000000000101043b000000000001041b0000000101000039000000000001042d0000000001000019000000000001042d000000000100001900001665000104300000065501000041000000000010043f0000001101000039000000040010043f000006210100004100001665000104300000065501000041000000000010043f0000003201000039000000040010043f000006210100004100001665000104300000065501000041000000000010043f0000003101000039000000040010043f00000621010000410000166500010430000000000001042f0000059a0010009c0000059a0100804100000040011002100000059a0020009c0000059a020080410000006002200210000000000112019f00000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f000005a3011001c700008010020000391663165e0000040f0000000100200190000016390000613d000000000101043b000000000001042d0000000001000019000016650001043000000000050100190000000000200443000000050030008c000016490000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000016410000413d0000059a0030009c0000059a03008041000000600130021000000000020004140000059a0020009c0000059a02008041000000c002200210000000000112019f00000661011001c700000000020500191663165e0000040f0000000100200190000016580000613d000000000101043b000000000001042d000000000001042f0000165c002104210000000102000039000000000001042d0000000002000019000000000001042d00001661002104230000000102000039000000000001042d0000000002000019000000000001042d0000166300000432000016640001042e00001665000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff9a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf426561726973684869626561726e6174696f6e00000000000000000000000000310000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f02000000000000000000000000000000000000a0000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e00000000200000000000000000000000000000200000001000000000000000000000000000000000000000000000000000000000000000000000000007ecebdff00000000000000000000000000000000000000000000000000000000baa51f8500000000000000000000000000000000000000000000000000000000e8fe76d400000000000000000000000000000000000000000000000000000000f7c618c000000000000000000000000000000000000000000000000000000000fed80d4200000000000000000000000000000000000000000000000000000000fed80d4300000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000f7c618c100000000000000000000000000000000000000000000000000000000fdaff82d00000000000000000000000000000000000000000000000000000000f0f4425f00000000000000000000000000000000000000000000000000000000f0f4426000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e8fe76d500000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000d5a44f8500000000000000000000000000000000000000000000000000000000e0b5541500000000000000000000000000000000000000000000000000000000e0b5541600000000000000000000000000000000000000000000000000000000e64a21f300000000000000000000000000000000000000000000000000000000d5a44f8600000000000000000000000000000000000000000000000000000000d8ee36cb00000000000000000000000000000000000000000000000000000000d30207d400000000000000000000000000000000000000000000000000000000d30207d500000000000000000000000000000000000000000000000000000000d56d229d00000000000000000000000000000000000000000000000000000000baa51f8600000000000000000000000000000000000000000000000000000000bec92aa1000000000000000000000000000000000000000000000000000000008eff1a9700000000000000000000000000000000000000000000000000000000a7693c8900000000000000000000000000000000000000000000000000000000ab08d4fb00000000000000000000000000000000000000000000000000000000ab08d4fc00000000000000000000000000000000000000000000000000000000ac86e18600000000000000000000000000000000000000000000000000000000a7693c8a00000000000000000000000000000000000000000000000000000000a972985e0000000000000000000000000000000000000000000000000000000099d271a10000000000000000000000000000000000000000000000000000000099d271a200000000000000000000000000000000000000000000000000000000a694fc3a000000000000000000000000000000000000000000000000000000008eff1a9800000000000000000000000000000000000000000000000000000000917bb9980000000000000000000000000000000000000000000000000000000084b0196d000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008df40be80000000000000000000000000000000000000000000000000000000084b0196e0000000000000000000000000000000000000000000000000000000088c0771b000000000000000000000000000000000000000000000000000000007ecebe0000000000000000000000000000000000000000000000000000000000817b1cd2000000000000000000000000000000000000000000000000000000008456cb5900000000000000000000000000000000000000000000000000000000313dab1f000000000000000000000000000000000000000000000000000000006548b7ad0000000000000000000000000000000000000000000000000000000074a238420000000000000000000000000000000000000000000000000000000075bba1880000000000000000000000000000000000000000000000000000000075bba189000000000000000000000000000000000000000000000000000000007808184b0000000000000000000000000000000000000000000000000000000074a23843000000000000000000000000000000000000000000000000000000007564a48b000000000000000000000000000000000000000000000000000000006b0509b0000000000000000000000000000000000000000000000000000000006b0509b100000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000006548b7ae0000000000000000000000000000000000000000000000000000000066fd3aba000000000000000000000000000000000000000000000000000000003f4ba839000000000000000000000000000000000000000000000000000000005c975aba000000000000000000000000000000000000000000000000000000005c975abb0000000000000000000000000000000000000000000000000000000061d027b3000000000000000000000000000000000000000000000000000000003f4ba83a0000000000000000000000000000000000000000000000000000000054d1f13d00000000000000000000000000000000000000000000000000000000313dab20000000000000000000000000000000000000000000000000000000003425677e000000000000000000000000000000000000000000000000000000003874390400000000000000000000000000000000000000000000000000000000187958810000000000000000000000000000000000000000000000000000000025692961000000000000000000000000000000000000000000000000000000002d0335aa000000000000000000000000000000000000000000000000000000002d0335ab000000000000000000000000000000000000000000000000000000002e17de780000000000000000000000000000000000000000000000000000000025692962000000000000000000000000000000000000000000000000000000002b4f585200000000000000000000000000000000000000000000000000000000230f436c00000000000000000000000000000000000000000000000000000000230f436d0000000000000000000000000000000000000000000000000000000024b2341a0000000000000000000000000000000000000000000000000000000018795882000000000000000000000000000000000000000000000000000000001e372dc4000000000000000000000000000000000000000000000000000000000981348100000000000000000000000000000000000000000000000000000000150b7a0100000000000000000000000000000000000000000000000000000000150b7a0200000000000000000000000000000000000000000000000000000000167653910000000000000000000000000000000000000000000000000000000009813482000000000000000000000000000000000000000000000000000000000dee32f7000000000000000000000000000000000000000000000000000000000406aa610000000000000000000000000000000000000000000000000000000004e8690300000000000000000000000000000000000000000000000000000000052dd76900000000000000000000000000000000000000000000000000000000389a75e100000000000000000000000000000000000000200000008000000000000000002d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb000000000000000000000000000000000000000000000000ffffffffffffffff02000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffff796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000020000000000000000000000000000000000002000000000000000000000000099d35d310c9c945374857b12c5aacd15c228347336e834aede361cb66f176d34310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c00000000000000004ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a02000000000000000000000000000000000000200000000c0000000000000000000000000000000000000000000000000000000000000000000000006f5e88180200000000000000000000000000000000000040000000800000000000000000b38780ddde1f073d91c150de2696f3f7085883648ba21cc5ef01029cb21d19160000000000000000000000000000000000000000000000929eee149b4bd2126802000002000000000000000000000000000000440000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000023b872dd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000009b99f7b307a6ccb858ed7807c962ea0b671f34f7782a046a180b3fdc2ae70593f27b6ce5b2f5e68ddb2fd95a8a909d4ecf1daaac270935fff052feacb24f184200000000000000000000000000000000000000200000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000021e27c1806e59a400006352211e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000ffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffff00000000000000000000000000000000000000006e8910ae8080a58abd08134c664ce6d891d2355c172dc66c7a66bb8d9e66a7c9032bc66be43dbccb7487781d168eb7bda224628a3b2c3388bdf69b532a3a161156f5046a9512d1a5348e2eecb62d47d89de20355eaab322a5b0b64500e5d96b700000000000000000000000000000000a9059cbb00000000000000000000000000000000000000000000000000000000000000440000001000000000000000000000000000000000000000000000000000000000000000000000000090b8ec18c51b56711f920e7b82b227c89cf5776728d779ff7a77da028652cee157e902bb6383b2d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000005ee2181dfa6de3967e89fb130ac3069014db0115a7909237eb145f41f88386880f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000200000000000000000000000000000000000020000000800000000000000000553d0173aaf3da5fa192882a6593e57e95cbf10b294e2e1d5e60806cbeced462858420e900000000000000000000000000000000000000000000000000000000d79a486e00000000000000000000000000000000000000000000000000000000d92e233d00000000000000000000000000000000000000000000000000000000e30826d778da7d768eb0d53d1cce09ef9a58bde3a4ff7ea2999c64d00924dc49ee055495f1bc14e67db7914a3182a05148748ae5803a9853e5ef1614f7a1ba8e897035f006971d702b7abbc980533b1c7ddd4bca05ce1c208d3348fcaddc770e756688fe00000000000000000000000000000000000000000000000000000000969bf72800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f000000000000000000000000000000000000000000000000190100000000000002000000000000000000000000000000000000420000001800000000000000001626ba7e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff9bffffffffffffffffffffffffffffffffffffff9c0000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000000000640000001c0000000000000000000000000000000000000000000000000000000000000000000000007939f424987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a8baa579f000000000000000000000000000000000000000000000000000000000819bdcd00000000000000000000000000000000000000000000000000000000501c54ac00000000000000000000000000000000000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c920000000000000000000000000000000000000000000000000000000082b42900dd62ed3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000080000000000000000070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000800000000000000000cd79e7ec00000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d59dc379f0000000000000000000000000000000000000000000000000000000016e9ad8f0000000000000000000000000000000000000000000000000000000082b42900000000000000000000000000000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000055809984000000000000000000000000000000000000000000000000000000002926ef0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab143c06f8af67e5000000000000000000000000000000000000000000000000000000009e87fac800000000000000000000000000000000000000000000000000000000150b7a020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cd702e318940000000000000000000000000000000000000040000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0020000020000000000000000000000000000000000000000000000000000000000ba523b06cca7fe6b7c96269109e255108c3749e3639398ec698fd3c5aeb5fc

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

000000000000000000000000516dc288e26b34557f68ea1c1ff13576eff8a1680000000000000000000000004b16703f7b0de03d23fd54606ed5786a59e3f27e000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a00000000000000000000000000000000000000000000000000001cd702e31894

-----Decoded View---------------
Arg [0] : _nftContract (address): 0x516DC288e26b34557f68EA1c1Ff13576Eff8a168
Arg [1] : _rewardToken (address): 0x4B16703f7B0de03D23FD54606ed5786a59E3f27e
Arg [2] : _treasury (address): 0xC8F65219949995DEB1390B60F60855a278a2262A
Arg [3] : _owner (address): 0xC8F65219949995DEB1390B60F60855a278a2262A
Arg [4] : _claimSigner (address): 0xC8F65219949995DEB1390B60F60855a278a2262A
Arg [5] : _moderator (address): 0xC8F65219949995DEB1390B60F60855a278a2262A
Arg [6] : _ratePerSecond (uint256): 31709791983764

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000516dc288e26b34557f68ea1c1ff13576eff8a168
Arg [1] : 0000000000000000000000004b16703f7b0de03d23fd54606ed5786a59e3f27e
Arg [2] : 000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a
Arg [3] : 000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a
Arg [4] : 000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a
Arg [5] : 000000000000000000000000c8f65219949995deb1390b60f60855a278a2262a
Arg [6] : 00000000000000000000000000000000000000000000000000001cd702e31894


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.