Arbitrum Sepolia Testnet

Token

vePost NFT (vePOST)
ERC-721

Overview

Max Total Supply

196.768473437195860266 vePOST

Holders

12

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-
Balance
0 vePOST
0x0000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
VePost

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 19 : VePost.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/governance/IGovernor.sol";
import "../../interfaces/IRevenueShares.sol";
import "../../interfaces/IReaderUniSwapPosition.sol";
import "../helper/VePostNFTSVG.sol";
import "../../interfaces/IVePostNFTSVG.sol";
import "../../interfaces/IPostGovernor.sol";

import "hardhat/console.sol";

/**
@title Voting Escrow
@author Curve Finance
@license MIT
@notice Votes have a weight depending on time, so that users are
committed to the future of (whatever they are voting for)
@dev Vote weight decays linearly over time. Lock time cannot be
more than `MAXTIME` (4 years).

# Voting escrow to have time-weighted votes
# Votes have a weight depending on time, so that users are committed
# to the future of (whatever they are voting for).
# The weight in this implementation is linear, and lock cannot be more than maxtime:
# w ^
# 1 +        /
#   |      /
#   |    /
#   |  /
#   |/
# 0 +--------+------> time
#       maxtime (4 years?)
*/

struct Point {
    int128 bias;
    int128 slope; // # -dweight / dt
    uint ts;
    uint blk; // block
}
/* We cannot really do block numbers per se b/c slope is per time, not per block
 * and per block could be fairly bad b/c Ethereum changes blocktimes.
 * What we can do is to extrapolate ***At functions */

struct LockedBalance {
    int128 amount;
    uint end;
    uint start;
    uint32 boostMultiplier;
}

contract VePost is Ownable, IERC721, IERC721Metadata {
    enum DepositType {
        DEPOSIT_FOR_TYPE,
        CREATE_LOCK_TYPE,
        CREATE_LOCK_NFT_LP_TYPE,
        INCREASE_LOCK_AMOUNT,
        INCREASE_UNLOCK_TIME
    }

    enum LockType {
        NONE,
        TOKEN_POST,
        LP_NFT
    }

    event Deposit(
        address indexed provider,
        uint tokenId,
        uint value,
        uint indexed locktime,
        DepositType deposit_type,
        uint ts
    );
    event Withdraw(address indexed provider, uint tokenId, uint value, uint ts);
    event Supply(uint prevSupply, uint supply, uint ts);

    uint internal constant WEEK = 1 weeks;
    uint internal constant MAXTIME = 4 * 365 * 86400;
    uint internal constant MINTIME = 90 * 86400;
    int128 internal constant iMAXTIME = 4 * 365 * 86400;
    uint internal constant MULTIPLIER = 1 ether;

    uint32 public constant BASE_PERCENT = 10_000;

    address public immutable token;
    uint public supply;
    mapping(uint => LockedBalance) public locked;

    mapping(uint => uint) public ownership_change;

    uint public epoch;
    mapping(uint => Point) public point_history; // epoch -> unsigned point
    mapping(uint => Point[10000000000]) public user_point_history; // user -> Point[user_epoch]

    mapping(uint => uint) public user_point_epoch;
    mapping(uint => int128) public slope_changes; // time -> signed slope change

    /// mapping contract from post.tech
    mapping(address => bool) public whiteListContractPostTech;

    // mapping vePost to uniSwap nft LP
    mapping(uint256 => uint256) public vePostToLPNft;

    /// mapping tokenId vePost to type of depost: token or LP NFT
    mapping(uint256 => LockType) public lockType;

    /// we dont allow transfer vePost when stake
    /// we dont allow increase vePost when stake
    mapping(uint256 => bool) public isLockVeWhenStake;

    mapping(address => bool) public handlers;

    /// Contract voting
    address public voter;

    // tracking the user participate voting
    mapping(address => bool) public voted;

    // tracking the current proposal participate voting
    mapping(address => uint256) public votingProposal;

    IERC721 public lpNft;

    uint32 public boostMultiplier = 20_000;

    /// @dev min is 10_000
    uint32 public boostToken = 12_000;

    /// @dev min is 10_000
    uint32 public boostLPNft = 15_000;

    /// @dev IMPORTANT
    /// In case user long time no vesting
    /// if this vePost expired, we extend time below
    /// for user claim and withdraw before we set average weight to default zero
    uint32 public bufferTimeToCalAverageWeight = 3 days;

    /// The contract tracking revenue share user
    IRevenueShares public revenueShares;

    IReaderUniSwapPosition public readerUniSwapPosition;

    IVePostNFTSVG public vePostNFTSVG;

    string public constant name = "vePost NFT";
    string public constant symbol = "vePOST";
    string public constant version = "1.0.0";
    uint8 public constant decimals = 18;

    /// @dev Current count of token
    uint internal tokenId = 10000;

    /// @dev Mapping from NFT ID to the address that owns it.
    mapping(uint => address) internal idToOwner;

    /// @dev Mapping from NFT ID to approved address.
    mapping(uint => address) internal idToApprovals;

    /// @dev Mapping from owner address to count of his tokens.
    mapping(address => uint) internal ownerToNFTokenCount;

    /// @dev Mapping from owner address to mapping of index to tokenIds
    mapping(address => mapping(uint => uint)) internal ownerToNFTokenIdList;

    /// @dev Mapping from NFT ID to index of owner
    mapping(uint => uint) internal tokenToOwnerIndex;

    /// @dev Mapping from owner address to mapping of operator addresses.
    mapping(address => mapping(address => bool)) internal ownerToOperators;

    /// @dev Mapping of interface id to bool about whether or not it's supported
    mapping(bytes4 => bool) internal supportedInterfaces;

    /// @dev ERC165 interface ID of ERC165
    bytes4 internal constant ERC165_INTERFACE_ID = 0x01ffc9a7;

    /// @dev ERC165 interface ID of ERC721
    bytes4 internal constant ERC721_INTERFACE_ID = 0x80ac58cd;

    /// @dev ERC165 interface ID of ERC721Metadata
    bytes4 internal constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;

    /// @dev reentrancy guard
    uint8 internal constant _not_entered = 1;
    uint8 internal constant _entered = 2;
    uint8 internal _entered_state = 1;
    modifier nonreentrant() {
        require(_entered_state == _not_entered);
        _entered_state = _entered;
        _;
        _entered_state = _not_entered;
    }

    modifier onlyHandler() {
        require(handlers[msg.sender], "only handler");
        _;
    }

    /// @notice Contract constructor
    /// @param token_addr `ERC20CRV` token address
    constructor(
        address token_addr,
        address _lpNft,
        address _vePostNFTSVG
    ) Ownable(msg.sender) {
        token = token_addr;
        voter = msg.sender;
        vePostNFTSVG = IVePostNFTSVG(_vePostNFTSVG);
        lpNft = IERC721(_lpNft);
        point_history[0].blk = _blockNumber();
        point_history[0].ts = _blockTimeStamp();

        supportedInterfaces[ERC165_INTERFACE_ID] = true;
        supportedInterfaces[ERC721_INTERFACE_ID] = true;
        supportedInterfaces[ERC721_METADATA_INTERFACE_ID] = true;

        // mint-ish
        emit Transfer(address(0), address(this), tokenId);
        // burn-ish
        emit Transfer(address(this), address(0), tokenId);
    }

    /// @dev Interface identification is specified in ERC-165.
    /// @param _interfaceID Id of the interface
    function supportsInterface(
        bytes4 _interfaceID
    ) external view returns (bool) {
        return supportedInterfaces[_interfaceID];
    }

    /// @notice Get the most recently recorded rate of voting power decrease for `_tokenId`
    /// @param _tokenId token of the NFT
    /// @return Value of the slope
    function get_last_user_slope(uint _tokenId) external view returns (int128) {
        uint uepoch = user_point_epoch[_tokenId];
        return user_point_history[_tokenId][uepoch].slope;
    }

    /// @notice Get the timestamp for checkpoint `_idx` for `_tokenId`
    /// @param _tokenId token of the NFT
    /// @param _idx User epoch number
    /// @return Epoch time of the checkpoint
    function user_point_history__ts(
        uint _tokenId,
        uint _idx
    ) external view returns (uint) {
        return user_point_history[_tokenId][_idx].ts;
    }

    /// @notice Get timestamp when `_tokenId`'s lock finishes
    /// @param _tokenId User NFT
    /// @return Epoch time of the lock end
    function locked__end(uint _tokenId) external view returns (uint) {
        return locked[_tokenId].end;
    }

    /// @dev Returns the number of NFTs owned by `_owner`.
    ///      Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.
    /// @param _owner Address for whom to query the balance.
    function _balance(address _owner) internal view returns (uint) {
        return ownerToNFTokenCount[_owner];
    }

    /// @dev Returns the number of NFTs owned by `_owner`.
    ///      Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.
    /// @param _owner Address for whom to query the balance.
    function balanceOf(address _owner) external view returns (uint) {
        return _balance(_owner);
    }

    /// @dev Returns the address of the owner of the NFT.
    /// @param _tokenId The identifier for an NFT.
    function ownerOf(uint _tokenId) public view returns (address) {
        return idToOwner[_tokenId];
    }

    /// @dev Get the approved address for a single NFT.
    /// @param _tokenId ID of the NFT to query the approval of.
    function getApproved(uint _tokenId) external view returns (address) {
        return idToApprovals[_tokenId];
    }

    /// @dev Checks if `_operator` is an approved operator for `_owner`.
    /// @param _owner The address that owns the NFTs.
    /// @param _operator The address that acts on behalf of the owner.
    function isApprovedForAll(
        address _owner,
        address _operator
    ) external view returns (bool) {
        return (ownerToOperators[_owner])[_operator];
    }

    /// @dev  Get token by index
    function tokenOfOwnerByIndex(
        address _owner,
        uint _tokenIndex
    ) public view returns (uint) {
        return ownerToNFTokenIdList[_owner][_tokenIndex];
    }

    /// #dev Get all tokens id by user
    /// @param owner address of the nfts to query
    function tokensOfOwner(
        address owner
    ) public view returns (uint256[] memory) {
        uint256 balance = _balance(owner);
        uint256[] memory tokens = new uint256[](balance);

        for (uint256 i = 0; i < balance; i++) {
            tokens[i] = tokenOfOwnerByIndex(owner, i);
        }
        return tokens;
    }

    struct VePostDetail {
        uint128 amount;
        uint end;
        uint start;
        uint32 boostMultiplier;
        LockType lockType;
        uint256 currentWeight;
        uint256 tokenId;
    }

    /// @dev Get detail vePost by owner and time
    /// @param owner address of the nfts to query
    /// @param t timestamp to query weight
    function tokensDetailOfOwner(
        address owner,
        uint256 t
    ) public view returns (VePostDetail[] memory) {
        uint256 balance = _balance(owner);
        VePostDetail[] memory tokensDetail = new VePostDetail[](balance);

        uint256 _tokenId;
        LockedBalance memory _lock;
        uint256 _weight;
        if (t == 0) {
            t = _blockTimeStamp();
        }

        for (uint i = 0; i < balance; i++) {
            _tokenId = tokenOfOwnerByIndex(owner, i);
            _lock = locked[_tokenId];
            _weight = _balanceOfNFT(_tokenId, t);
            tokensDetail[i] = VePostDetail({
                tokenId: _tokenId,
                amount: uint128(_lock.amount),
                end: _lock.end,
                start: _lock.start,
                boostMultiplier: _lock.boostMultiplier,
                lockType: lockType[_tokenId],
                currentWeight: _weight
            });
        }

        return tokensDetail;
    }

    /// @dev get total weight of all vePost at the time
    function getTotalWeightOfOwner(
        address owner,
        uint timestamp
    ) external view returns (uint256 totalWeight) {
        uint256[] memory tokenIds = tokensOfOwner(owner);

        if (tokenIds.length == 0) {
            return 0;
        }
        if (timestamp == 0) {
            timestamp = block.timestamp;
        }
        for (uint256 i = 0; i < tokenIds.length; i++) {
            totalWeight += balanceOfNFTAt(tokenIds[i], timestamp);
        }

        return totalWeight;
    }

    /// @dev get average weight of all vePost at the time
    function getAverageWeightOfOwner(
        address owner,
        uint timestamp
    ) external view returns (uint256 averageWeight) {
        uint256 totalWeight;
        uint256[] memory tokenIds = tokensOfOwner(owner);
        if (tokenIds.length == 0) {
            return 0;
        }
        if (timestamp == 0) {
            timestamp = block.timestamp;
        }
        for (uint256 i = 0; i < tokenIds.length; i++) {
            totalWeight += balanceOfNFTAt(tokenIds[i], timestamp);
        }

        averageWeight = totalWeight / tokenIds.length;
    }

    /// @dev Returns whether the given spender can transfer a given token ID
    /// @param _spender address of the spender to query
    /// @param _tokenId uint ID of the token to be transferred
    /// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token
    function _isApprovedOrOwner(
        address _spender,
        uint _tokenId
    ) internal view returns (bool) {
        address owner = idToOwner[_tokenId];
        bool spenderIsOwner = owner == _spender;
        bool spenderIsApproved = _spender == idToApprovals[_tokenId];
        bool spenderIsApprovedForAll = (ownerToOperators[owner])[_spender];
        return spenderIsOwner || spenderIsApproved || spenderIsApprovedForAll;
    }

    function isApprovedOrOwner(
        address _spender,
        uint _tokenId
    ) external view returns (bool) {
        return _isApprovedOrOwner(_spender, _tokenId);
    }

    /// @dev Add a NFT to an index mapping to a given address
    /// @param _to address of the receiver
    /// @param _tokenId uint ID Of the token to be added
    function _addTokenToOwnerList(address _to, uint _tokenId) internal {
        uint current_count = _balance(_to);

        ownerToNFTokenIdList[_to][current_count] = _tokenId;
        tokenToOwnerIndex[_tokenId] = current_count;
    }

    /// @dev Remove a NFT from an index mapping to a given address
    /// @param _from address of the sender
    /// @param _tokenId uint ID Of the token to be removed
    function _removeTokenFromOwnerList(address _from, uint _tokenId) internal {
        // Delete
        uint current_count = _balance(_from) - 1;
        uint current_index = tokenToOwnerIndex[_tokenId];

        if (current_count == current_index) {
            // update ownerToNFTokenIdList
            ownerToNFTokenIdList[_from][current_count] = 0;
            // update tokenToOwnerIndex
            tokenToOwnerIndex[_tokenId] = 0;
        } else {
            uint lastTokenId = ownerToNFTokenIdList[_from][current_count];

            // Add
            // update ownerToNFTokenIdList
            ownerToNFTokenIdList[_from][current_index] = lastTokenId;
            // update tokenToOwnerIndex
            tokenToOwnerIndex[lastTokenId] = current_index;

            // Delete
            // update ownerToNFTokenIdList
            ownerToNFTokenIdList[_from][current_count] = 0;
            // update tokenToOwnerIndex
            tokenToOwnerIndex[_tokenId] = 0;
        }
    }

    /// @dev Add a NFT to a given address
    ///      Throws if `_tokenId` is owned by someone.
    function _addTokenTo(address _to, uint _tokenId) internal {
        // Throws if `_tokenId` is owned by someone
        assert(idToOwner[_tokenId] == address(0));
        // Change the owner
        idToOwner[_tokenId] = _to;
        // Update owner token index tracking
        _addTokenToOwnerList(_to, _tokenId);
        // Change count tracking
        ownerToNFTokenCount[_to] += 1;
    }

    /// @dev Remove a NFT from a given address
    ///      Throws if `_from` is not the current owner.
    function _removeTokenFrom(address _from, uint _tokenId) internal {
        // Throws if `_from` is not the current owner
        assert(idToOwner[_tokenId] == _from);
        // Change the owner
        idToOwner[_tokenId] = address(0);
        // Update owner token index tracking
        _removeTokenFromOwnerList(_from, _tokenId);
        // Change count tracking
        ownerToNFTokenCount[_from] -= 1;
    }

    /// @dev Clear an approval of a given address
    ///      Throws if `_owner` is not the current owner.
    function _clearApproval(address _owner, uint _tokenId) internal {
        // Throws if `_owner` is not the current owner
        assert(idToOwner[_tokenId] == _owner);
        if (idToApprovals[_tokenId] != address(0)) {
            // Reset approvals
            idToApprovals[_tokenId] = address(0);
        }
    }

    /// @dev transfer tracking revenue to other users
    function _transferRevenueTracking(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal {
        // If transfer to whitelist contract post.tech
        // must not take transfer revenue tracking;
        // If transfer from whitelist contract post.tech
        // must not take transfer revenue tracking too
        if (
            !whiteListContractPostTech[_to] && !whiteListContractPostTech[_from]
        ) {
            revenueShares.transferRevenueTracking(_from, _to, _tokenId);
        }
    }

    /// @dev Exeute transfer of a NFT.
    ///      Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
    ///      address for this NFT. (NOTE: `msg.sender` not allowed in internal function so pass `_sender`.)
    ///      Throws if `_to` is the zero address.
    ///      Throws if `_from` is not the current owner.
    ///      Throws if `_tokenId` is not a valid NFT.
    function _transferFrom(
        address _from,
        address _to,
        uint _tokenId,
        address _sender
    ) internal {
        _resetVote(_from);
        require(!voted[_from], "token in voting");
        require(!isLockVeWhenStake[tokenId], "must not lock transfer");
        // Check requirements
        require(_isApprovedOrOwner(_sender, _tokenId), "Not owner token");

        // transfer revenue tracking to `_to`
        _transferRevenueTracking(_from, _to, _tokenId);

        // Clear approval. Throws if `_from` is not the current owner
        _clearApproval(_from, _tokenId);
        // Remove NFT. Throws if `_tokenId` is not a valid NFT
        _removeTokenFrom(_from, _tokenId);
        // Add NFT
        _addTokenTo(_to, _tokenId);
        // Set the block of ownership transfer (for Flash NFT protection)
        ownership_change[_tokenId] = _blockNumber();
        // Log the transfer
        emit Transfer(_from, _to, _tokenId);
    }

    /* TRANSFER FUNCTIONS */
    /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT.
    ///      Throws if `_from` is not the current owner.
    ///      Throws if `_to` is the zero address.
    ///      Throws if `_tokenId` is not a valid NFT.
    /// @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
    ///        they maybe be permanently lost.
    /// @param _from The current owner of the NFT.
    /// @param _to The new owner.
    /// @param _tokenId The NFT to transfer.
    function transferFrom(address _from, address _to, uint _tokenId) external {
        _transferFrom(_from, _to, _tokenId, msg.sender);
    }

    function _isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.
        uint size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /// @dev Transfers the ownership of an NFT from one address to another address.
    ///      Throws unless `msg.sender` is the current owner, an authorized operator, or the
    ///      approved address for this NFT.
    ///      Throws if `_from` is not the current owner.
    ///      Throws if `_to` is the zero address.
    ///      Throws if `_tokenId` is not a valid NFT.
    ///      If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if
    ///      the return value is not `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`.
    /// @param _from The current owner of the NFT.
    /// @param _to The new owner.
    /// @param _tokenId The NFT to transfer.
    /// @param _data Additional data with no specified format, sent in call to `_to`.
    function safeTransferFrom(
        address _from,
        address _to,
        uint _tokenId,
        bytes memory _data
    ) public {
        _transferFrom(_from, _to, _tokenId, msg.sender);

        if (_isContract(_to)) {
            // Throws if transfer destination is a contract which does not implement 'onERC721Received'
            try
                IERC721Receiver(_to).onERC721Received(
                    msg.sender,
                    _from,
                    _tokenId,
                    _data
                )
            returns (bytes4) {} catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert(
                        "ERC721: transfer to non ERC721Receiver implementer"
                    );
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }

    /// @dev Transfers the ownership of an NFT from one address to another address.
    ///      Throws unless `msg.sender` is the current owner, an authorized operator, or the
    ///      approved address for this NFT.
    ///      Throws if `_from` is not the current owner.
    ///      Throws if `_to` is the zero address.
    ///      Throws if `_tokenId` is not a valid NFT.
    ///      If `_to` is a smart contract, it calls `onERC721Received` on `_to` and throws if
    ///      the return value is not `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`.
    /// @param _from The current owner of the NFT.
    /// @param _to The new owner.
    /// @param _tokenId The NFT to transfer.
    function safeTransferFrom(
        address _from,
        address _to,
        uint _tokenId
    ) external {
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    /// @dev Set or reaffirm the approved address for an NFT. The zero address indicates there is no approved address.
    ///      Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.
    ///      Throws if `_tokenId` is not a valid NFT. (NOTE: This is not written the EIP)
    ///      Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)
    /// @param _approved Address to be approved for the given NFT ID.
    /// @param _tokenId ID of the token to be approved.
    function approve(address _approved, uint _tokenId) public {
        address owner = idToOwner[_tokenId];
        // Throws if `_tokenId` is not a valid NFT
        require(owner != address(0));
        // Throws if `_approved` is the current owner
        require(_approved != owner);
        // Check requirements
        bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);
        bool senderIsApprovedForAll = (ownerToOperators[owner])[msg.sender];
        require(senderIsOwner || senderIsApprovedForAll);
        // Set the approval
        idToApprovals[_tokenId] = _approved;
        emit Approval(owner, _approved, _tokenId);
    }

    /// @dev Enables or disables approval for a third party ("operator") to manage all of
    ///      `msg.sender`'s assets. It also emits the ApprovalForAll event.
    ///      Throws if `_operator` is the `msg.sender`. (NOTE: This is not written the EIP)
    /// @notice This works even if sender doesn't own any tokens at the time.
    /// @param _operator Address to add to the set of authorized operators.
    /// @param _approved True if the operators is approved, false to revoke approval.
    function setApprovalForAll(address _operator, bool _approved) external {
        // Throws if `_operator` is the `msg.sender`
        assert(_operator != msg.sender);
        ownerToOperators[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

    /// @dev Function to mint tokens
    ///      Throws if `_to` is zero address.
    ///      Throws if `_tokenId` is owned by someone.
    /// @param _to The address that will receive the minted tokens.
    /// @param _tokenId The token id to mint.
    /// @return A boolean that indicates if the operation was successful.
    function _mint(address _to, uint _tokenId) internal returns (bool) {
        // Throws if `_to` is zero address
        assert(_to != address(0));
        // Add NFT. Throws if `_tokenId` is owned by someone
        _addTokenTo(_to, _tokenId);
        emit Transfer(address(0), _to, _tokenId);
        return true;
    }

    /// @notice Record global and per-user data to checkpoint
    /// @param _tokenId NFT token ID. No user checkpoint if 0
    /// @param old_locked Previous locked amount / end lock time for the user
    /// @param new_locked New locked amount / end lock time for the user
    function _checkpoint(
        uint _tokenId,
        LockedBalance memory old_locked,
        LockedBalance memory new_locked
    ) internal {
        Point memory u_old;
        Point memory u_new;
        int128 old_dslope = 0;
        int128 new_dslope = 0;
        uint _epoch = epoch;

        if (_tokenId != 0) {
            // Calculate slopes and biases
            // Kept at zero when they have to
            if (old_locked.end > _blockTimeStamp() && old_locked.amount > 0) {
                u_old.slope =
                    (int32(old_locked.boostMultiplier) * old_locked.amount) /
                    (iMAXTIME * int32(BASE_PERCENT));
                u_old.bias =
                    u_old.slope *
                    int128(int256(old_locked.end - _blockTimeStamp()));
            }
            if (new_locked.end > _blockTimeStamp() && new_locked.amount > 0) {
                u_new.slope =
                    (int32(new_locked.boostMultiplier) * new_locked.amount) /
                    (iMAXTIME * int32(BASE_PERCENT));
                u_new.bias =
                    u_new.slope *
                    int128(int256(new_locked.end - _blockTimeStamp()));
            }

            // Read values of scheduled changes in the slope
            // old_locked.end can be in the past and in the future
            // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros
            old_dslope = slope_changes[old_locked.end];
            if (new_locked.end != 0) {
                if (new_locked.end == old_locked.end) {
                    new_dslope = old_dslope;
                } else {
                    new_dslope = slope_changes[new_locked.end];
                }
            }
        }

        Point memory last_point = Point({
            bias: 0,
            slope: 0,
            ts: _blockTimeStamp(),
            blk: _blockNumber()
        });
        if (_epoch > 0) {
            last_point = point_history[_epoch];
        }
        uint last_checkpoint = last_point.ts;
        // initial_last_point is used for extrapolation to calculate block number
        // (approximately, for *At methods) and save them
        // as we cannot figure that out exactly from inside the contract
        Point memory initial_last_point = last_point;
        uint block_slope = 0; // dblock/dt
        if (_blockTimeStamp() > last_point.ts) {
            block_slope =
                (MULTIPLIER * (_blockNumber() - last_point.blk)) /
                (_blockTimeStamp() - last_point.ts);
        }
        // If last point is already recorded in this block, slope=0
        // But that's ok b/c we know the block in such case

        // Go over weeks to fill history and calculate what the current point is
        {
            uint t_i = (last_checkpoint / WEEK) * WEEK;
            for (uint i = 0; i < 255; ++i) {
                // Hopefully it won't happen that this won't get used in 5 years!
                // If it does, users will be able to withdraw but vote weight will be broken
                t_i += WEEK;
                int128 d_slope = 0;
                if (t_i > _blockTimeStamp()) {
                    t_i = _blockTimeStamp();
                } else {
                    d_slope = slope_changes[t_i];
                }
                last_point.bias -=
                    last_point.slope *
                    int128(int256(t_i - last_checkpoint));
                last_point.slope += d_slope;
                if (last_point.bias < 0) {
                    // This can happen
                    last_point.bias = 0;
                }
                if (last_point.slope < 0) {
                    // This cannot happen - just in case
                    last_point.slope = 0;
                }
                last_checkpoint = t_i;
                last_point.ts = t_i;
                last_point.blk =
                    initial_last_point.blk +
                    (block_slope * (t_i - initial_last_point.ts)) /
                    MULTIPLIER;
                _epoch += 1;
                if (t_i == _blockTimeStamp()) {
                    last_point.blk = _blockNumber();
                    break;
                } else {
                    point_history[_epoch] = last_point;
                }
            }
        }

        epoch = _epoch;
        // Now point_history is filled until t=now

        if (_tokenId != 0) {
            // If last point was in this block, the slope change has been applied already
            // But in such case we have 0 slope(s)
            last_point.slope += (u_new.slope - u_old.slope);
            last_point.bias += (u_new.bias - u_old.bias);
            if (last_point.slope < 0) {
                last_point.slope = 0;
            }
            if (last_point.bias < 0) {
                last_point.bias = 0;
            }
        }

        // Record the changed point into history
        point_history[_epoch] = last_point;

        if (_tokenId != 0) {
            // Schedule the slope changes (slope is going down)
            // We subtract new_user_slope from [new_locked.end]
            // and add old_user_slope to [old_locked.end]
            if (old_locked.end > _blockTimeStamp()) {
                // old_dslope was <something> - u_old.slope, so we cancel that
                old_dslope += u_old.slope;
                if (new_locked.end == old_locked.end) {
                    old_dslope -= u_new.slope; // It was a new deposit, not extension
                }
                slope_changes[old_locked.end] = old_dslope;
            }

            if (new_locked.end > _blockTimeStamp()) {
                if (new_locked.end > old_locked.end) {
                    new_dslope -= u_new.slope; // old slope disappeared at this point
                    slope_changes[new_locked.end] = new_dslope;
                }
                // else: we recorded it already in old_dslope
            }
            // Now handle user history
            uint user_epoch = user_point_epoch[_tokenId] + 1;

            user_point_epoch[_tokenId] = user_epoch;
            u_new.ts = _blockTimeStamp();
            u_new.blk = _blockNumber();
            user_point_history[_tokenId][user_epoch] = u_new;
        }
    }

    /// @notice Deposit and lock tokens for a user
    /// @param _tokenId NFT that holds lock
    /// @param _value Amount to deposit
    /// @param unlock_time New time when to unlock the tokens, or 0 if unchanged
    /// @param locked_balance Previous locked amount / timestamp
    /// @param deposit_type The type of deposit
    function _deposit_for(
        uint _tokenId,
        uint _value,
        uint unlock_time,
        LockedBalance memory locked_balance,
        DepositType deposit_type
    ) internal {
        LockedBalance memory _locked = locked_balance;
        uint supply_before = supply;

        supply = supply_before + _value;
        LockedBalance memory old_locked;
        (old_locked.amount, old_locked.end, old_locked.boostMultiplier) = (
            _locked.amount,
            _locked.end,
            _locked.boostMultiplier
        );
        // Adding to existing lock, or if a lock is expired - creating a new one
        _locked.amount += int128(int256(_value));
        if (unlock_time != 0) {
            _locked.end = unlock_time;
        }
        if (_locked.start == 0) {
            _locked.start = _blockTimeStamp();
        }

        if (_locked.boostMultiplier == 0) {
            uint32 _boostMultiplier = BASE_PERCENT;

            if (deposit_type == DepositType.CREATE_LOCK_NFT_LP_TYPE) {
                _boostMultiplier =
                    (boostLPNft * boostMultiplier) /
                    BASE_PERCENT;
            } else if (deposit_type == DepositType.CREATE_LOCK_TYPE) {
                _boostMultiplier =
                    (boostToken * boostMultiplier) /
                    BASE_PERCENT;
            }

            old_locked.boostMultiplier = _boostMultiplier;
            _locked.boostMultiplier = _boostMultiplier;
        }

        locked[_tokenId] = _locked;

        // Possibilities:
        // Both old_locked.end could be current or expired (>/< _blockTimeStamp())
        // value == 0 (extend lock) or value > 0 (add to lock or extend lock)
        // _locked.end > _blockTimeStamp() (always)
        _checkpoint(_tokenId, old_locked, _locked);

        address from = msg.sender;
        if (
            _value != 0 && deposit_type != DepositType.CREATE_LOCK_NFT_LP_TYPE
        ) {
            assert(IERC20(token).transferFrom(from, address(this), _value));
        }

        emit Deposit(
            from,
            _tokenId,
            _value,
            _locked.end,
            deposit_type,
            _blockTimeStamp()
        );
        emit Supply(supply_before, supply_before + _value, _blockTimeStamp());
    }

    function _increase_tracking_revenue(
        address user,
        uint256 _tokenId
    ) internal {
        revenueShares.supply(user, _tokenId);
    }

    function _update_reward(address user) internal {
        revenueShares.claimRewardFor(user);
    }

    function _decrease_tracking_revenue(
        address user,
        uint256 _tokenId
    ) internal {
        revenueShares.removeSupply(user, _tokenId);
    }

    function shuttleRevenueTracking(uint256 _tokenId) external onlyHandler {
        revenueShares.shuttlesRevenueByTokenId(_tokenId);
    }

    /// @notice Record global data to checkpoint
    function checkpoint() external {
        _checkpoint(0, LockedBalance(0, 0, 0, 0), LockedBalance(0, 0, 0, 0));
    }

    /// @notice Deposit `_value` tokens for `_tokenId` and add to the lock
    /// @dev Anyone (even a smart contract) can deposit for someone else, but
    ///      cannot extend their locktime and deposit for a brand new user
    /// @param _tokenId lock NFT
    /// @param _value Amount to add to user's lock
    function deposit_for(uint _tokenId, uint _value) external nonreentrant {
        LockedBalance memory _locked = locked[_tokenId];
        require(vePostToLPNft[_tokenId] == 0, "Must not is uniSwap nft lp");

        require(_value > 0); // dev: need non-zero value
        require(_locked.amount > 0, "No existing lock found");
        require(
            _locked.end > _blockTimeStamp(),
            "Cannot add to expired lock. Withdraw"
        );
        /// increase tracking revenue from post.tech
        revenueShares.updateSupply(
            ownerOf(_tokenId),
            _tokenId,
            uint128(_locked.amount) + uint128(_value)
        );
        _deposit_for(
            _tokenId,
            _value,
            0,
            _locked,
            DepositType.DEPOSIT_FOR_TYPE
        );
    }

    /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`
    /// @param _value Amount to deposit
    /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
    /// @param _to Address to deposit
    function _create_lock(
        uint _value,
        uint _lock_duration,
        address _to,
        DepositType deposit_type
    ) internal returns (uint) {
        uint unlock_time = ((_blockTimeStamp() + _lock_duration) / WEEK) * WEEK; // Locktime is rounded down to weeks

        require(_value > 0, "Invalid value"); // dev: need non-zero value
        require(
            unlock_time > _blockTimeStamp(),
            "Can only lock until time in the future"
        );
        require(
            unlock_time <= _blockTimeStamp() + MAXTIME,
            "Voting lock can be 4 years max"
        );
        require(_lock_duration >= MINTIME, "Voting lock must 3 months min");

        ++tokenId;
        uint _tokenId = tokenId;
        _mint(_to, _tokenId);

        if (deposit_type == DepositType.CREATE_LOCK_NFT_LP_TYPE) {
            lockType[_tokenId] = LockType.LP_NFT;
        } else if (deposit_type == DepositType.CREATE_LOCK_TYPE) {
            lockType[_tokenId] = LockType.TOKEN_POST;
        }

        /// update tracking reward
        _update_reward(_to);
        _deposit_for(
            _tokenId,
            _value,
            unlock_time,
            locked[_tokenId],
            deposit_type
        );
        /// increase tracking revenue from post.tech
        _increase_tracking_revenue(_to, _tokenId);

        return _tokenId;
    }

    /// @notice Deposit `_value` tokens for `_to` and lock for `_lock_duration`
    /// @param _value Amount to deposit
    /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
    /// @param _to Address to deposit
    function create_lock_for(
        uint _value,
        uint _lock_duration,
        address _to
    ) external nonreentrant returns (uint) {
        return
            _create_lock(
                _value,
                _lock_duration,
                _to,
                DepositType.CREATE_LOCK_TYPE
            );
    }

    /// @notice Deposit `_uni_lp_token_id` uniSwap for `_to` and lock for `_lock_duration`
    /// @param _uni_lp_token_id tokenId of uniSwap
    /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
    /// @param _to Address to deposit
    function create_lock_nft_lp_for(
        uint256 _uni_lp_token_id,
        uint _lock_duration,
        address _to
    ) external nonreentrant returns (uint) {
        (uint256 _postAmount, ) = readerUniSwapPosition.getUniV3NFTValueInfo(
            _uni_lp_token_id
        );

        require(_postAmount > 0, "No post amount in LP NFT");

        // record tracking
        lpNft.transferFrom(msg.sender, address(this), _uni_lp_token_id);

        uint256 _tokenId = _create_lock(
            _postAmount,
            _lock_duration,
            _to,
            DepositType.CREATE_LOCK_NFT_LP_TYPE
        );

        vePostToLPNft[_tokenId] = _uni_lp_token_id;
        return _tokenId;
    }

    /// @notice Deposit `_value` tokens for `msg.sender` and lock for `_lock_duration`
    /// @param _value Amount to deposit
    /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
    function create_lock(
        uint _value,
        uint _lock_duration
    ) external nonreentrant returns (uint) {
        return
            _create_lock(
                _value,
                _lock_duration,
                msg.sender,
                DepositType.CREATE_LOCK_TYPE
            );
    }

    /// @notice Deposit `_uni_lp_token_id` uniSwap for `msg.sender` and lock for `_lock_duration`
    /// @param _uni_lp_token_id Amount to deposit
    /// @param _lock_duration Number of seconds to lock tokens for (rounded down to nearest week)
    function create_lock_nft_lp(
        uint256 _uni_lp_token_id,
        uint _lock_duration
    ) external nonreentrant returns (uint) {
        (uint256 _postAmount, ) = readerUniSwapPosition.getUniV3NFTValueInfo(
            _uni_lp_token_id
        );

        require(_postAmount > 0, "No post amount in LP NFT");

        // record tracking
        lpNft.transferFrom(msg.sender, address(this), _uni_lp_token_id);
        uint256 _tokenId = _create_lock(
            _postAmount,
            _lock_duration,
            msg.sender,
            DepositType.CREATE_LOCK_NFT_LP_TYPE
        );

        vePostToLPNft[_tokenId] = _uni_lp_token_id;
        return _tokenId;
    }

    /// @notice Deposit `_value` additional tokens for `_tokenId` without modifying the unlock time
    /// @param _value Amount of tokens to deposit and add to the lock
    function increase_amount(uint _tokenId, uint _value) external nonreentrant {
        require(_isApprovedOrOwner(msg.sender, _tokenId), "Not owner of token");
        require(!isLockVeWhenStake[_tokenId], "must not lock when stake");
        require(vePostToLPNft[_tokenId] == 0, "Must not is uniSwap nft lp");

        LockedBalance memory _locked = locked[_tokenId];

        require(_value > 0, "Invalid amount"); // dev: need non-zero value
        require(_locked.amount > 0, "No existing lock found");
        require(
            _locked.end > _blockTimeStamp(),
            "Cannot add to expired lock. Withdraw"
        );

        /// increase tracking revenue from post.tech
        revenueShares.updateSupply(
            msg.sender,
            _tokenId,
            uint128(_locked.amount) + uint128(_value)
        );

        _deposit_for(
            _tokenId,
            _value,
            0,
            _locked,
            DepositType.INCREASE_LOCK_AMOUNT
        );
    }

    /// @notice Extend the unlock time for `_tokenId`
    /// @param _lock_duration New number of seconds until tokens unlock
    function increase_unlock_time(
        uint _tokenId,
        uint _lock_duration
    ) external nonreentrant {
        require(_isApprovedOrOwner(msg.sender, _tokenId), "Not owner of token");
        require(!isLockVeWhenStake[_tokenId], "must not lock when stake");

        LockedBalance memory _locked = locked[_tokenId];
        uint unlock_time = ((_blockTimeStamp() + _lock_duration) / WEEK) * WEEK; // Locktime is rounded down to weeks

        require(_locked.end > _blockTimeStamp(), "Lock expired");
        require(_locked.amount > 0, "Nothing is locked");
        require(unlock_time > _locked.end, "Can only increase lock duration");
        require(
            unlock_time <= _blockTimeStamp() + MAXTIME,
            "Voting lock can be 4 years max"
        );

        _locked.start = _blockTimeStamp();

        /// tracking revenue from post.tech
        _update_reward(msg.sender);

        _deposit_for(
            _tokenId,
            0,
            unlock_time,
            _locked,
            DepositType.INCREASE_UNLOCK_TIME
        );
    }

    /// @notice Withdraw all tokens for `_tokenId`
    /// @dev Only possible if the lock has expired
    function withdraw(uint _tokenId) external nonreentrant {
        _withdraw(_tokenId, msg.sender);
    }

    /// @notice Withdraw all tokens for `_tokenId` for owner of token
    /// @dev Only possible if the lock has expired
    function withdrawFor(uint _tokenId) external nonreentrant {
        address ownerOfToken = ownerOf(_tokenId);
        _withdraw(_tokenId, ownerOfToken);
    }

    /// @notice lock vePost when staked
    /// @dev set value isLockVeWhenStake[_tokenId] = true when stake
    ///      only handler can call
    function lockWhenStake(uint256 _tokenId) external onlyHandler {
        isLockVeWhenStake[_tokenId] = true;
    }

    /// @notice unlock vePost when unStaked
    /// @dev set value isLockVeWhenStake[_tokenId] = false when stake
    ///      only handler  can call
    function unLockWhenStake(uint256 _tokenId) external onlyHandler {
        isLockVeWhenStake[_tokenId] = false;
    }

    function _withdraw(uint256 _tokenId, address ownerOfToken) internal {
        require(
            _isApprovedOrOwner(ownerOfToken, _tokenId),
            "Not owner of token"
        );
        require(!isLockVeWhenStake[_tokenId], "must not lock when stake");
        address _ownerOfToken = ownerOf(_tokenId);
        _resetVote(_ownerOfToken);
        require(!voted[_ownerOfToken], "token in voting");

        /// decrease tracking revenue from post.tech
        /// MUST call first because when burn and no tokenId data to tracking
        _decrease_tracking_revenue(ownerOfToken, _tokenId);

        LockedBalance memory _locked = locked[_tokenId];
        require(_blockTimeStamp() >= _locked.end, "The lock didn't expire");
        uint value = uint(int256(_locked.amount));

        locked[_tokenId] = LockedBalance(0, 0, 0, 0);
        uint supply_before = supply;
        supply = supply_before - value;

        // old_locked can have either expired <= timestamp or zero end
        // _locked has only 0 end
        // Both can have >= 0 amount
        _checkpoint(_tokenId, _locked, LockedBalance(0, 0, 0, 0));

        uint256 _tokenNftLpId = vePostToLPNft[_tokenId];

        if (_tokenNftLpId == 0) {
            assert(IERC20(token).transfer(ownerOfToken, value));
        } else {
            lpNft.transferFrom(address(this), ownerOfToken, _tokenNftLpId);
            vePostToLPNft[_tokenId] = 0;
        }
        lockType[_tokenId] = LockType.NONE;

        // Burn the NFT
        _burn(_tokenId);

        emit Withdraw(ownerOfToken, _tokenId, value, _blockTimeStamp());
        emit Supply(supply_before, supply_before - value, _blockTimeStamp());
    }

    // The following ERC20/minime-compatible methods are not real balanceOf and supply!
    // They measure the weights for the purpose of voting, so they don't represent
    // real coins.

    /// @notice Binary search to estimate timestamp for block number
    /// @param _block Block to find
    /// @param max_epoch Don't go beyond this epoch
    /// @return Approximate timestamp for block
    function _find_block_epoch(
        uint _block,
        uint max_epoch
    ) internal view returns (uint) {
        // Binary search
        uint _min = 0;
        uint _max = max_epoch;
        for (uint i = 0; i < 128; ++i) {
            // Will be always enough for 128-bit numbers
            if (_min >= _max) {
                break;
            }
            uint _mid = (_min + _max + 1) / 2;
            if (point_history[_mid].blk <= _block) {
                _min = _mid;
            } else {
                _max = _mid - 1;
            }
        }
        return _min;
    }

    /// @notice Get the current voting power for `_tokenId`
    /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
    /// @param _tokenId NFT for lock
    /// @param _t Epoch time to return voting power at
    /// @return User voting power
    function _balanceOfNFT(
        uint _tokenId,
        uint _t
    ) internal view returns (uint) {
        uint _epoch = user_point_epoch[_tokenId];

        if (_epoch == 0) {
            return 0;
        } else {
            Point memory last_point = user_point_history[_tokenId][_epoch];
            last_point.bias -=
                last_point.slope *
                int128(int256(_t) - int256(last_point.ts));
            if (last_point.bias < 0) {
                last_point.bias = 0;
            }
            return uint(int256(last_point.bias));
        }
    }

    /// @dev calculate average one weight in range time
    /// @param _tokenId NFT for lock
    /// @param startTime start time to calculate average weight
    /// @param endTime end time to calculate average weight
    function averageWeightInTime(
        uint _tokenId,
        uint256 startTime,
        uint256 endTime
    ) external view returns (uint256) {
        LockedBalance memory lock = locked[_tokenId];

        if (endTime > lock.end) {
            if (endTime - lock.end < bufferTimeToCalAverageWeight) {
                endTime = lock.end;
            } else {
                return 0;
            }
        }

        if (startTime > endTime || lock.amount == 0) {
            return 0;
        }

        uint256 integralWeigh = (_balanceOfNFT(_tokenId, startTime) +
            _balanceOfNFT(_tokenId, endTime)) / 2;

        return integralWeigh;
    }

    /// @dev calculate average multi weight in range time
    /// @param tokenIds NFT for lock
    /// @param startTime start time to calculate average weight
    /// @param endTime end time to calculate average weight
    function averageMultiWeightInTime(
        uint[] memory tokenIds,
        uint256 startTime,
        uint256 endTime
    ) external view returns (uint256) {
        uint256 totalIntegralWeigh = 0;
        uint256 countToken = 0;

        for (uint i = 0; i < tokenIds.length; i++) {
            LockedBalance memory lock = locked[tokenIds[i]];

            if (lock.amount == 0) {
                continue;
            }
            countToken++;

            if (endTime > lock.end) {
                if (endTime - lock.end < bufferTimeToCalAverageWeight) {
                    endTime = lock.end;
                } else {
                    continue;
                }
            }

            uint256 integralWeigh = 0;
            if (startTime < endTime) {
                integralWeigh =
                    (_balanceOfNFT(tokenIds[i], startTime) +
                        _balanceOfNFT(tokenIds[i], endTime)) /
                    2;
            }
            totalIntegralWeigh += integralWeigh;
        }

        return countToken == 0 ? 0 : totalIntegralWeigh / countToken;
    }

    /// @dev Returns current token URI metadata
    /// @param _tokenId Token ID to fetch URI for.
    function tokenURI(uint _tokenId) external view returns (string memory) {
        require(
            idToOwner[_tokenId] != address(0),
            "Query for nonexistent token"
        );
        LockedBalance memory _locked = locked[_tokenId];

        return
            vePostNFTSVG.buildVePost(
                _tokenId,
                lockType[_tokenId] == LockType.TOKEN_POST ? 1 : 2,
                _locked.start,
                _locked.end,
                _blockTimeStamp(),
                _locked.boostMultiplier,
                _balanceOfNFT(_tokenId, _blockTimeStamp())
            );
    }

    function balanceOfNFT(uint _tokenId) external view returns (uint) {
        if (ownership_change[_tokenId] == _blockNumber()) return 0;
        return _balanceOfNFT(_tokenId, _blockTimeStamp());
    }

    function balanceOfNFTAt(uint _tokenId, uint _t) public view returns (uint) {
        return _balanceOfNFT(_tokenId, _t);
    }

    /// @notice Measure voting power of `_tokenId` at block height `_block`
    /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime
    /// @param _tokenId User's wallet NFT
    /// @param _block Block to calculate the voting power at
    /// @return Voting power
    function _balanceOfAtNFT(
        uint _tokenId,
        uint _block
    ) internal view returns (uint) {
        // Copying and pasting totalSupply code because Vyper cannot pass by
        // reference yet
        assert(_block <= _blockNumber());

        // Binary search
        uint _min = 0;
        uint _max = user_point_epoch[_tokenId];
        for (uint i = 0; i < 128; ++i) {
            // Will be always enough for 128-bit numbers
            if (_min >= _max) {
                break;
            }
            uint _mid = (_min + _max + 1) / 2;
            if (user_point_history[_tokenId][_mid].blk <= _block) {
                _min = _mid;
            } else {
                _max = _mid - 1;
            }
        }

        Point memory upoint = user_point_history[_tokenId][_min];

        uint max_epoch = epoch;
        uint _epoch = _find_block_epoch(_block, max_epoch);
        Point memory point_0 = point_history[_epoch];
        uint d_block = 0;
        uint d_t = 0;
        if (_epoch < max_epoch) {
            Point memory point_1 = point_history[_epoch + 1];
            d_block = point_1.blk - point_0.blk;
            d_t = point_1.ts - point_0.ts;
        } else {
            d_block = _blockNumber() - point_0.blk;
            d_t = _blockTimeStamp() - point_0.ts;
        }
        uint block_time = point_0.ts;
        if (d_block != 0) {
            block_time += (d_t * (_block - point_0.blk)) / d_block;
        }

        upoint.bias -= upoint.slope * int128(int256(block_time - upoint.ts));
        if (upoint.bias >= 0) {
            return uint(uint128(upoint.bias));
        } else {
            return 0;
        }
    }

    function balanceOfAtNFT(
        uint _tokenId,
        uint _block
    ) external view returns (uint) {
        return _balanceOfAtNFT(_tokenId, _block);
    }

    /// @notice Calculate total voting power at some point in the past
    /// @param point The point (bias/slope) to start search from
    /// @param t Time to calculate the total voting power at
    /// @return Total voting power at that time
    function _supply_at(
        Point memory point,
        uint t
    ) internal view returns (uint) {
        Point memory last_point = point;
        uint t_i = (last_point.ts / WEEK) * WEEK;
        for (uint i = 0; i < 255; ++i) {
            t_i += WEEK;
            int128 d_slope = 0;
            if (t_i > t) {
                t_i = t;
            } else {
                d_slope = slope_changes[t_i];
            }
            last_point.bias -=
                last_point.slope *
                int128(int256(t_i - last_point.ts));
            if (t_i == t) {
                break;
            }
            last_point.slope += d_slope;
            last_point.ts = t_i;
        }

        if (last_point.bias < 0) {
            last_point.bias = 0;
        }
        return uint(uint128(last_point.bias));
    }

    /// @notice Calculate total voting power
    /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
    /// @return Total voting power
    function totalSupplyAtT(uint t) public view returns (uint) {
        uint _epoch = epoch;
        Point memory last_point = point_history[_epoch];
        return _supply_at(last_point, t);
    }

    function totalSupply() external view returns (uint) {
        return totalSupplyAtT(_blockTimeStamp());
    }

    /// @notice Calculate total voting power at some point in the past
    /// @param _block Block to calculate the total voting power at
    /// @return Total voting power at `_block`
    function totalSupplyAt(uint _block) external view returns (uint) {
        assert(_block <= _blockNumber());
        uint _epoch = epoch;
        uint target_epoch = _find_block_epoch(_block, _epoch);

        Point memory point = point_history[target_epoch];
        uint dt = 0;
        if (target_epoch < _epoch) {
            Point memory point_next = point_history[target_epoch + 1];
            if (point.blk != point_next.blk) {
                dt =
                    ((_block - point.blk) * (point_next.ts - point.ts)) /
                    (point_next.blk - point.blk);
            }
        } else {
            if (point.blk != _blockNumber()) {
                dt =
                    ((_block - point.blk) * (_blockTimeStamp() - point.ts)) /
                    (_blockNumber() - point.blk);
            }
        }
        // Now dt contains info on how far are we beyond point
        return _supply_at(point, point.ts + dt);
    }

    function _blockTimeStamp() internal view returns (uint) {
        return block.timestamp;
    }

    function _blockNumber() internal view returns (uint) {
        return block.number;
    }

    function _abstain(address user) internal {
        voted[user] = false;
        votingProposal[user] = 0;
    }

    /// @dev check user is voting with all tokens
    ///      if the proposal pass active then reset vote and user can transfer
    ///      if the proposal in active then user can not transfer
    /// @param user address of user to check voting
    function _resetVote(address user) internal {
        uint256 proposal = votingProposal[user];
        if (proposal == 0) {
            return;
        }
        IGovernor.ProposalState proposalState = IPostGovernor(voter).state(
            proposal
        );
        if (proposalState != IGovernor.ProposalState.Active) {
            _abstain(user);
        }
    }

    function _burn(uint _tokenId) internal {
        require(
            _isApprovedOrOwner(msg.sender, _tokenId),
            "caller is not owner nor approved"
        );

        address owner = ownerOf(_tokenId);

        // Clear approval
        approve(address(0), _tokenId);
        // Remove token
        _removeTokenFrom(msg.sender, _tokenId);
        emit Transfer(owner, address(0), _tokenId);
    }

    /// @dev set user is voting with all tokens
    ///      user can not transfer while proposal is active
    function voting(address user, uint256 proposalId) external {
        require(msg.sender == voter, "only Gov");
        voted[user] = true;
        votingProposal[user] = proposalId;
    }

    function abstain(address user) external {
        require(msg.sender == voter, "only Gov");
        _resetVote(user);
    }

    /// @dev reset vote when proposal not in active
    function resetVote() external {
        _resetVote(msg.sender);
    }

    function setBufferTimeToCalAverageWeight(
        uint32 _bufferTimeToCalAverageWeight
    ) external onlyOwner {
        bufferTimeToCalAverageWeight = _bufferTimeToCalAverageWeight;
    }

    function setHandler(address _handler, bool isHandler) external onlyOwner {
        handlers[_handler] = isHandler;
    }

    function setBoostMultiplier(uint32 _boostMultiplier) external onlyOwner {
        boostMultiplier = _boostMultiplier;
    }

    function setBoostToken(uint32 _boostToken) external onlyOwner {
        require(_boostToken >= BASE_PERCENT, "boostToken must >= BASE_PERCENT");
        boostToken = _boostToken;
    }

    function setBoostLPNft(uint32 _boostLPNft) external onlyOwner {
        require(
            _boostLPNft >= BASE_PERCENT,
            "_boostLPNft must >= BASE_PERCENT"
        );
        boostLPNft = _boostLPNft;
    }

    function setLPNft(address _lpNft) external onlyOwner {
        lpNft = IERC721(_lpNft);
    }

    function setVoter(address _voter) external onlyOwner {
        voter = _voter;
    }

    function setRevenueShares(address _revenueShares) external onlyOwner {
        revenueShares = IRevenueShares(_revenueShares);
    }

    function setReaderUniSwapPosition(
        address _readerUniSwapPosition
    ) external onlyOwner {
        readerUniSwapPosition = IReaderUniSwapPosition(_readerUniSwapPosition);
    }

    function setVePostSVG(address _vePostSVG) external onlyOwner {
        vePostNFTSVG = IVePostNFTSVG(_vePostSVG);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (governance/IGovernor.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../interfaces/IERC165.sol";
import {IERC6372} from "../interfaces/IERC6372.sol";

/**
 * @dev Interface of the {Governor} core.
 */
interface IGovernor is IERC165, IERC6372 {
    enum ProposalState {
        Pending,
        Active,
        Canceled,
        Defeated,
        Succeeded,
        Queued,
        Expired,
        Executed
    }

    /**
     * @dev Empty proposal or a mismatch between the parameters length for a proposal call.
     */
    error GovernorInvalidProposalLength(uint256 targets, uint256 calldatas, uint256 values);

    /**
     * @dev The vote was already cast.
     */
    error GovernorAlreadyCastVote(address voter);

    /**
     * @dev Token deposits are disabled in this contract.
     */
    error GovernorDisabledDeposit();

    /**
     * @dev The `account` is not a proposer.
     */
    error GovernorOnlyProposer(address account);

    /**
     * @dev The `account` is not the governance executor.
     */
    error GovernorOnlyExecutor(address account);

    /**
     * @dev The `proposalId` doesn't exist.
     */
    error GovernorNonexistentProposal(uint256 proposalId);

    /**
     * @dev The current state of a proposal is not the required for performing an operation.
     * The `expectedStates` is a bitmap with the bits enabled for each ProposalState enum position
     * counting from right to left.
     *
     * NOTE: If `expectedState` is `bytes32(0)`, the proposal is expected to not be in any state (i.e. not exist).
     * This is the case when a proposal that is expected to be unset is already initiated (the proposal is duplicated).
     *
     * See {Governor-_encodeStateBitmap}.
     */
    error GovernorUnexpectedProposalState(uint256 proposalId, ProposalState current, bytes32 expectedStates);

    /**
     * @dev The voting period set is not a valid period.
     */
    error GovernorInvalidVotingPeriod(uint256 votingPeriod);

    /**
     * @dev The `proposer` does not have the required votes to create a proposal.
     */
    error GovernorInsufficientProposerVotes(address proposer, uint256 votes, uint256 threshold);

    /**
     * @dev The `proposer` is not allowed to create a proposal.
     */
    error GovernorRestrictedProposer(address proposer);

    /**
     * @dev The vote type used is not valid for the corresponding counting module.
     */
    error GovernorInvalidVoteType();

    /**
     * @dev Queue operation is not implemented for this governor. Execute should be called directly.
     */
    error GovernorQueueNotImplemented();

    /**
     * @dev The proposal hasn't been queued yet.
     */
    error GovernorNotQueuedProposal(uint256 proposalId);

    /**
     * @dev The proposal has already been queued.
     */
    error GovernorAlreadyQueuedProposal(uint256 proposalId);

    /**
     * @dev The provided signature is not valid for the expected `voter`.
     * If the `voter` is a contract, the signature is not valid using {IERC1271-isValidSignature}.
     */
    error GovernorInvalidSignature(address voter);

    /**
     * @dev Emitted when a proposal is created.
     */
    event ProposalCreated(
        uint256 proposalId,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 voteStart,
        uint256 voteEnd,
        string description
    );

    /**
     * @dev Emitted when a proposal is queued.
     */
    event ProposalQueued(uint256 proposalId, uint256 etaSeconds);

    /**
     * @dev Emitted when a proposal is executed.
     */
    event ProposalExecuted(uint256 proposalId);

    /**
     * @dev Emitted when a proposal is canceled.
     */
    event ProposalCanceled(uint256 proposalId);

    /**
     * @dev Emitted when a vote is cast without params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     */
    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);

    /**
     * @dev Emitted when a vote is cast with params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     * `params` are additional encoded parameters. Their interpepretation also depends on the voting module used.
     */
    event VoteCastWithParams(
        address indexed voter,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string reason,
        bytes params
    );

    /**
     * @notice module:core
     * @dev Name of the governor instance (used in building the ERC712 domain separator).
     */
    function name() external view returns (string memory);

    /**
     * @notice module:core
     * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
     */
    function version() external view returns (string memory);

    /**
     * @notice module:voting
     * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
     * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
     * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
     *
     * There are 2 standard keys: `support` and `quorum`.
     *
     * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
     * - `quorum=bravo` means that only For votes are counted towards quorum.
     * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
     *
     * If a counting module makes use of encoded `params`, it should  include this under a `params` key with a unique
     * name that describes the behavior. For example:
     *
     * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
     * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
     *
     * NOTE: The string can be decoded by the standard
     * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
     * JavaScript class.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() external view returns (string memory);

    /**
     * @notice module:core
     * @dev Hashing function used to (re)build the proposal id from the proposal details..
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) external pure returns (uint256);

    /**
     * @notice module:core
     * @dev Current state of a proposal, following Compound's convention
     */
    function state(uint256 proposalId) external view returns (ProposalState);

    /**
     * @notice module:core
     * @dev The number of votes required in order for a voter to become a proposer.
     */
    function proposalThreshold() external view returns (uint256);

    /**
     * @notice module:core
     * @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the
     * snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the
     * following block.
     */
    function proposalSnapshot(uint256 proposalId) external view returns (uint256);

    /**
     * @notice module:core
     * @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is
     * possible to cast a vote during this block.
     */
    function proposalDeadline(uint256 proposalId) external view returns (uint256);

    /**
     * @notice module:core
     * @dev The account that created a proposal.
     */
    function proposalProposer(uint256 proposalId) external view returns (address);

    /**
     * @notice module:core
     * @dev The time when a queued proposal becomes executable ("ETA"). Unlike {proposalSnapshot} and
     * {proposalDeadline}, this doesn't use the governor clock, and instead relies on the executor's clock which may be
     * different. In most cases this will be a timestamp.
     */
    function proposalEta(uint256 proposalId) external view returns (uint256);

    /**
     * @notice module:core
     * @dev Whether a proposal needs to be queued before execution.
     */
    function proposalNeedsQueuing(uint256 proposalId) external view returns (bool);

    /**
     * @notice module:user-config
     * @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends
     * on the clock (see EIP-6372) this contract uses.
     *
     * This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a
     * proposal starts.
     *
     * NOTE: While this interface returns a uint256, timepoints are stored as uint48 following the ERC-6372 clock type.
     * Consequently this value must fit in a uint48 (when added to the current clock). See {IERC6372-clock}.
     */
    function votingDelay() external view returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock
     * (see EIP-6372) this contract uses.
     *
     * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
     * duration compared to the voting delay.
     *
     * NOTE: This value is stored when the proposal is submitted so that possible changes to the value do not affect
     * proposals that have already been submitted. The type used to save it is a uint32. Consequently, while this
     * interface returns a uint256, the value it returns should fit in a uint32.
     */
    function votingPeriod() external view returns (uint256);

    /**
     * @notice module:user-config
     * @dev Minimum number of cast voted required for a proposal to be successful.
     *
     * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the
     * quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}).
     */
    function quorum(uint256 timepoint) external view returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `timepoint`.
     *
     * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
     * multiple), {ERC20Votes} tokens.
     */
    function getVotes(address account, uint256 timepoint) external view returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `timepoint` given additional encoded parameters.
     */
    function getVotesWithParams(
        address account,
        uint256 timepoint,
        bytes memory params
    ) external view returns (uint256);

    /**
     * @notice module:voting
     * @dev Returns whether `account` has cast a vote on `proposalId`.
     */
    function hasVoted(uint256 proposalId, address account) external view returns (bool);

    /**
     * @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a
     * duration specified by {IGovernor-votingPeriod}.
     *
     * Emits a {ProposalCreated} event.
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) external returns (uint256 proposalId);

    /**
     * @dev Queue a proposal. Some governors require this step to be performed before execution can happen. If queuing
     * is not necessary, this function may revert.
     * Queuing a proposal requires the quorum to be reached, the vote to be successful, and the deadline to be reached.
     *
     * Emits a {ProposalQueued} event.
     */
    function queue(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) external returns (uint256 proposalId);

    /**
     * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
     * deadline to be reached. Depending on the governor it might also be required that the proposal was queued and
     * that some delay passed.
     *
     * Emits a {ProposalExecuted} event.
     *
     * NOTE: Some modules can modify the requirements for execution, for example by adding an additional timelock.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) external payable returns (uint256 proposalId);

    /**
     * @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e.
     * before the vote starts.
     *
     * Emits a {ProposalCanceled} event.
     */
    function cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) external returns (uint256 proposalId);

    /**
     * @dev Cast a vote
     *
     * Emits a {VoteCast} event.
     */
    function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason
     *
     * Emits a {VoteCast} event.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) external returns (uint256 balance);

    /**
     * @dev Cast a vote using the voter's signature, including ERC-1271 signature support.
     *
     * Emits a {VoteCast} event.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        address voter,
        bytes memory signature
    ) external returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters using the voter's signature,
     * including ERC-1271 signature support.
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint8 support,
        address voter,
        string calldata reason,
        bytes memory params,
        bytes memory signature
    ) external returns (uint256 balance);
}

File 4 of 19 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC6372.sol)

pragma solidity ^0.8.20;

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

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

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

pragma solidity ^0.8.20;

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

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

    /**
     * @dev Returns the 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.0.0) (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.20;

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

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

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

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

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

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the 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);
}

File 9 of 19 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Base64.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // Loads the table into memory
        string memory table = _TABLE;

        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
        // and split into 4 numbers of 6 bits.
        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
        // - `data.length + 2`  -> Round up
        // - `/ 3`              -> Number of 3-bytes chunks
        // - `4 *`              -> 4 characters for each chunk
        string memory result = new string(4 * ((data.length + 2) / 3));

        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 32)

            // Run over the input, 3 bytes at a time
            for {
                let dataPtr := data
                let endPtr := add(data, mload(data))
            } lt(dataPtr, endPtr) {

            } {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 bytes (18 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F which is the number of
                // the previous character in the ASCII table prior to the Base64 Table
                // The result is then added to the table to get the character to write,
                // and finally write it in the result pointer but with a left shift
                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // When data `bytes` is not exactly 3 bytes long
            // it is padded with `=` characters at the end
            switch mod(mload(data), 3)
            case 1 {
                mstore8(sub(resultPtr, 1), 0x3d)
                mstore8(sub(resultPtr, 2), 0x3d)
            }
            case 2 {
                mstore8(sub(resultPtr, 1), 0x3d)
            }
        }

        return result;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

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

pragma solidity ^0.8.20;

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

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/Base64.sol";
import "../../interfaces/IVePost.sol";

contract VePostNFTSVG {
    IVePost public vePost;

    constructor(IVePost _vePost) {
        vePost = _vePost;
    }

    function buildVePost(
        uint256 tokenId,
        uint8 typeVePost, //0: None, 1: Token, 1: LP NFT
        uint256 startTimeLock,
        uint256 endTimeLock,
        uint256 currentTime,
        uint256 boost,
        uint256 currentWeight
    ) external view returns (string memory) {
        bytes memory svgImage = _buildImage(
            tokenId,
            typeVePost,
            startTimeLock,
            endTimeLock,
            currentTime,
            boost,
            currentWeight
        );

        bytes memory dataURI = abi.encodePacked(
            "{",
            '"name": "vePOST NFT #',
            _toString(tokenId),
            '",',
            '"description": "vePOST NFT by post.tech",',
            '"image": "',
            abi.encodePacked(
                "data:image/svg+xml;base64,",
                Base64.encode(svgImage)
            ),
            '"',
            "}"
        );
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(dataURI)
                )
            );
    }

    // <rect x="19.635" y="334" width="379" height="186" rx="12" fill="#283975" fill-opacity=".3"/>

    function _buildImage(
        uint256 tokenId,
        uint8 typeVePost, //0: None, 1: Token, 1: LP NFT
        uint256 startTimeLock,
        uint256 endTimeLock,
        uint256 currentTime,
        uint256 boost,
        uint256 currentWeight
    ) internal view returns (bytes memory) {
        return
            abi.encodePacked(
                '<svg width="202" height="278" viewBox="0 0 420 578" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)">',
                _buildBackground(typeVePost),
                '<g filter="url(#d)"><circle cx="273.285" cy="263.2" r="145.85" fill="#729BEC"/></g><g filter="url(#e)"><circle cx="209.635" cy="501.712" r="124.055" fill="#729BEC"/></g><g opacity=".6" filter="url(#f)"><circle cx="125.865" cy="191.515" r="83.445" fill="#729BEC"/></g></g><path d="M117 0h185v28c0 8.837-7.163 16-16 16H133c-8.837 0-16-7.163-16-16V0Z" fill="#fff" fill-opacity=".1"/>',
                _buildTypeNft(typeVePost),
                '<rect x="19.635" y="334" width="379" height="186" rx="12" fill="#283975" fill-opacity=".3"/><text fill="#F8FAFC" xml:space="preserve" style="white-space:pre" font-family="Arial" font-size="14" letter-spacing="0em"><tspan x="156.135" y="546.854">&#xa9;post.tech, 2023</tspan></text><path d="M313.937 291.002a17.453 17.453 0 0 1-9.379-3.831L86.304 112.39c-7.522-6.094-8.68-17.131-2.587-24.654 6.093-7.522 17.133-8.68 24.654-2.587l218.254 174.78c7.522 6.094 8.681 17.132 2.587 24.654-3.835 4.735-9.631 6.949-15.275 6.419Z" fill="url(#g)" opacity=".3"/>',
                _buildLocation(startTimeLock, endTimeLock, currentTime),
                _buildInformation(
                    startTimeLock,
                    endTimeLock,
                    tokenId,
                    boost,
                    currentWeight
                ),
                '<g filter="url(#i)"><path d="m337.913 286.625-11.255-41.042h-.002v-.002l-40.993-5.08c-1.781-2.739-5.492-7.07-12.468-9.974-7.326-12.498-20.369-14.833-30.058-15.434-18.608-.14-27.792 12.666-31.721 19.545 1.579-4.586 2.083-11.227 12.316-19.726 9.52-7.927 19.643-19.307 16.692-31.344-4.683-19.265-10.038-41.088 7.103-63.988-1.035.671-74.921 21.292-73.775 106.935 0 .476-1.426-21.827-21.054-35.719-18.69-14.344-42.793-28.394-45.253-47.799 0 0-43.577 103.384 37.984 140.348 8.081 3.663-3.65 17.335-11.688 21.096-5.922 2.955-20.942 11.142-20.942 11.142-16.473 9.016-25.206 25.808-31.246 32.658-.125.14-.196.21-.196.21.014 0 22.689-16.078 64.6-22.274 46.035-4.276 64.348-18.385 65.878-19.331 12.862-7.941 19.211-24.481 29.922-36.037 19.236-20.752 32.341-26.286 39.033-27.663l14.465 41.421.002-.001 42.656 2.059Z" fill="#fff" fill-opacity=".15"/></g><path d="M109.056 10.611H25.143c-8.837 0-16 7.164-16 16V550.96c0 8.837 7.163 16 16 16h367.654c8.837 0 16-7.163 16-16V26.611c0-8.836-7.163-16-16-16h-83.913" stroke="#fff" stroke-opacity=".4" stroke-width="2"/><defs><filter id="b" x="-129.476" y="-158.656" width="392" height="392" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="45" result="effect1_foregroundBlur_5235_408195"/></filter><filter id="c" x="9.486" y="-241.13" width="617.825" height="541.897" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="45" result="effect1_foregroundBlur_5235_408195"/></filter><filter id="d" x="30.209" y="20.124" width="486.151" height="486.152" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="48.613" result="effect1_foregroundBlur_5235_408195"/></filter><filter id="e" x="-18.889" y="273.188" width="457.048" height="457.048" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="52.235" result="effect1_foregroundBlur_5235_408195"/></filter><filter id="f" x="-54.806" y="10.844" width="361.342" height="361.341" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="48.613" result="effect1_foregroundBlur_5235_408195"/></filter><filter id="i" x="69.022" y="107.245" width="281.225" height="253.542" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="6.168" result="effect1_foregroundBlur_5235_408195"/></filter><linearGradient id="g" x1="173.928" y1="30.505" x2="268.083" y2="302.249" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="h" x1="196.956" y1="107.542" x2="185.747" y2="269.026" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><clipPath id="a"><rect x=".135" width="419" height="578" rx="24" fill="#fff"/></clipPath></defs></svg>'
            );
    }

    function _buildTypeNft(
        uint8 typeVePost
    ) internal pure returns (string memory) {
        string memory typeStringVePost;
        string memory locationText;

        if (typeVePost == 1) {
            typeStringVePost = "vePOST NFT";
            locationText = "160.5";
        } else if (typeVePost == 2) {
            typeStringVePost = "vePOST LP NFT";
            locationText = "147.5";
        } else {
            typeStringVePost = "vePOST Empty";
            locationText = "160.5";
        }

        return
            string(
                abi.encodePacked(
                    '<text fill="#F8FAFC" xml:space="preserve" style="white-space:pre" font-family="Arial" font-size="18" font-weight="bold" letter-spacing="0em">',
                    '<tspan x="',
                    locationText,
                    '" y="30.159">',
                    typeStringVePost,
                    "</tspan> </text>"
                )
            );
    }

    function _buildLocation(
        uint256 startTimeLock,
        uint256 endTimeLock,
        uint256 currentTime
    ) internal pure returns (string memory) {
        uint256 phaseTime = (endTimeLock - startTimeLock) / 7;
        uint256 currentPhase = currentTime - startTimeLock;
        string memory cx;
        string memory cy;

        if (currentPhase > 6 * phaseTime) {
            cx = "316.5";
            cy = "275.464";
        } else if (currentPhase > 5 * phaseTime) {
            cx = "281";
            cy = "246.463";
        } else if (currentPhase > 4 * phaseTime) {
            cx = "246.5";
            cy = "218.464";
        } else if (currentPhase > 3 * phaseTime) {
            cx = "207";
            cy = "186.464";
        } else if (currentPhase > 2 * phaseTime) {
            cx = "175.5";
            cy = "161.463";
        } else if (currentPhase > phaseTime) {
            cx = "137";
            cy = "130.464";
        } else {
            cx = "99.5";
            cy = "100.464";
        }

        return
            string(
                abi.encodePacked(
                    string(
                        abi.encodePacked(
                            '<path d="m96.747 98.139 55.912 44.667 55.912 44.668 111.824 89.335" stroke="url(#h)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>',
                            '<circle opacity=".1" cx="',
                            cx,
                            '" cy="',
                            cy,
                            '" r="32" fill="#fff"/>'
                        )
                    ),
                    string(
                        abi.encodePacked(
                            '<circle opacity=".3" cx="',
                            cx,
                            '" cy="',
                            cy,
                            '" r="18" fill="#fff"/>'
                        )
                    ),
                    string(
                        abi.encodePacked(
                            '<circle cx="',
                            cx,
                            '" cy="',
                            cy,
                            '" r="10" fill="#fff"/>'
                        )
                    )
                )
            );
    }

    function _buildBackground(
        uint8 lockType
    ) internal pure returns (string memory) {
        string memory color1 = lockType == 2 ? "#3088EB" : "#1565FE";
        string memory color2 = lockType == 2 ? "#6F49DC" : "#4473FF";
        string memory color3 = lockType == 2 ? "#8241D8" : "#567BFF";

        return
            string(
                abi.encodePacked(
                    '<path d="M394.809 0h-371c-13.255 0-24 10.745-24 24v530c0 13.255 10.745 24 24 24h371c13.254 0 24-10.745 24-24V24c0-13.255-10.746-24-24-24Z" fill="',
                    color1,
                    '"/><g filter="url(#b)"><circle cx="66.524" cy="37.344" r="106" fill="',
                    color2,
                    '"/></g>',
                    '<g filter="url(#c)"><ellipse cx="318.399" cy="29.819" rx="218.913" ry="180.949" fill="',
                    color3,
                    '"/></g>'
                )
            );
    }

    function _buildInformation(
        uint256 startTimeLock,
        uint256 endTimeLock,
        uint256 tokenId,
        uint256 boost,
        uint256 currentWeight
    ) internal view returns (string memory) {
        uint128 _pairValue = _getParValue(tokenId);
        return
            string(
                abi.encodePacked(
                    '<g font-family="Arial" font-size="22"><text fill="#E2E8F0" xml:space="preserve" style="white-space:pre" letter-spacing="0em"> <tspan x="36" y="370.934">ID: </tspan> </text><text fill="#F1F5F9" xml:space="preserve" style="white-space:pre" font-weight="bold" letter-spacing="-.005em" text-anchor="end"> <tspan x="380" y="370.934">#',
                    _toString(tokenId),
                    '</tspan></text><text fill="#E2E8F0" xml:space="preserve" style="white-space:pre" letter-spacing="0em"><tspan x="36" y="412.627">Boosted: </tspan></text><text fill="#F1F5F9" xml:space="preserve" style="white-space:pre" font-weight="bold" letter-spacing="-.005em" text-anchor="end"><tspan x="380" y="412.627">',
                    _buildBoost(startTimeLock, endTimeLock, boost),
                    '%</tspan></text><text fill="#E2E8F0" xml:space="preserve" style="white-space:pre" letter-spacing="0em"><tspan x="36" y="454.627">Par Value: </tspan></text><text fill="#F1F5F9" xml:space="preserve" style="white-space:pre" font-weight="bold" letter-spacing="-.005em" text-anchor="end"><tspan x="380" y="454.627">',
                    _buildNumberDecimal(_pairValue),
                    '</tspan></text><text fill="#E2E8F0" xml:space="preserve" style="white-space:pre" letter-spacing="0em"><tspan x="36" y="496.627">Current Power: </tspan></text><text fill="#F1F5F9" xml:space="preserve" style="white-space:pre" font-weight="bold" letter-spacing="-.005em" text-anchor="end"><tspan x="380" y="496.627">',
                    _buildNumberDecimal(currentWeight),
                    "</tspan></text></g>"
                )
            );
    }

    function _buildBoost(
        uint256 startTime,
        uint256 endTime,
        uint256 boosted
    ) internal pure returns (string memory) {
        uint256 boostPerTime = ((endTime - startTime) * 10_000) / 208 weeks;
        uint256 boost = (boosted * boostPerTime) / 10_000;
        uint256 decimal = boost % 100;
        string memory decimalStr = _toString(decimal);
        if (bytes(decimalStr).length == 0) {
            decimalStr = ".00";
        } else if (bytes(decimalStr).length == 1) {
            decimalStr = string.concat(".0", decimalStr);
        } else {
            decimalStr = string.concat(".", decimalStr);
        }

        string memory numberStr = _toString(boost / 100);

        return string.concat(numberStr, decimalStr);
    }

    function _getParValue(uint256 _tokenId) internal view returns (uint128) {
        (int128 amount, , , ) = vePost.locked(_tokenId);
        return uint128(amount);
    }

    function _toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT license
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

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

    function _buildNumberDecimal(
        uint256 _num
    ) internal pure returns (string memory) {
        if (_num == 0) {
            return "0";
        }

        string memory numberStr = _numberWithCommas(uint256(_num / 1e18));

        if (_num / 1e18 == 0) {
            numberStr = "0";
        }
        return string.concat(numberStr, _decimal(_num));
    }

    function _decimal(uint256 _num) internal pure returns (string memory) {
        uint256 mod = _num % 1e18;
        uint256 decimal = mod / 1e15;
        string memory decimalStr = _toString(decimal);
        if (bytes(decimalStr).length == 2) {
            decimalStr = string.concat("0", decimalStr);
        } else if (bytes(decimalStr).length == 1) {
            decimalStr = string.concat("00", decimalStr);
        }
        return string.concat(".", decimalStr);
    }

    function _numberWithCommas(
        uint256 _num
    ) internal pure returns (string memory) {
        string memory numStr = _toString(_num);
        uint256 length = bytes(numStr).length;
        if (length == 1) return numStr;
        uint256 commaCount = (length - 1) / 3;
        bytes memory result = new bytes(length + commaCount);

        uint256 i = length - 1;
        uint256 j = result.length - 1;
        uint256 commaAdded = 0;

        while (true) {
            result[j--] = bytes(numStr)[i--];
            commaAdded++;
            if (commaAdded % 3 == 0 && i >= 0) {
                result[j--] = ",";
            }
            if (i == 0) {
                result[j] = bytes(numStr)[0];
                break;
            }
        }
        return string(result);
    }
}

File 14 of 19 : IPostGovernor.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import "@openzeppelin/contracts/governance/IGovernor.sol";

interface IPostGovernor {
    function state(
        uint256 proposalId
    ) external view returns (IGovernor.ProposalState);
}

File 15 of 19 : IReaderUniSwapPosition.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

interface IReaderUniSwapPosition {
    function getUniV3NFTValueInfo(
        uint256 token_id
    ) external view returns (uint256 postAmount, uint256 flipAmount);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

interface IRevenueShares {
    function transferRevenueTracking(
        address from,
        address to,
        uint256 tokenId
    ) external;

    function supply(address user, uint256 tokenId) external;

    function removeSupply(address user, uint256 tokenId) external;

    function updateSupply(
        address user,
        uint256 tokenId,
        uint128 newSupply
    ) external;

    function mergeSupply(
        address user,
        uint256 fromTokenId,
        uint256 toTokenId
    ) external;

    function claimRewardFor(address account) external;

    function shuttlesRevenueByTokenId(uint256 tokenId) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

interface IVePost is IERC721 {
    enum LockType {
        NONE,
        TOKEN_POST,
        LP_NFT
    }

    struct VePostDetail {
        uint128 amount;
        uint end;
        uint start;
        uint32 boostMultiplier;
        LockType lockType;
        uint256 currentWeight;
        uint256 tokenId;
    }

    function balanceOfNFTAt(
        uint _tokenId,
        uint _t
    ) external view returns (uint);

    function ownerOf(uint _tokenId) external view returns (address);

    function locked(
        uint _tokenId
    )
        external
        view
        returns (int128 amount, uint end, uint start, uint32 boostMultiplier);

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

    function create_lock_nft_lp_for(
        uint256 _uni_lp_token_id,
        uint _lock_duration,
        address _to
    ) external returns (uint);

    function create_lock_for(
        uint _value,
        uint _lock_duration,
        address _to
    ) external returns (uint);

    function averageMultiWeightInTime(
        uint[] memory tokenIds,
        uint256 startTime,
        uint256 endTime
    ) external view returns (uint256);

    function lockType(uint _tokenId) external view returns (uint);

    function lockWhenStake(uint256 _tokenId) external;

    function isLockVeWhenStake(uint256 _tokenId) external view returns (bool);

    function unLockWhenStake(uint256 _tokenId) external;

    function getTotalWeightOfOwner(
        address owner,
        uint timestamp
    ) external view returns (uint256 totalWeight);

    function getAverageWeightOfOwner(
        address owner,
        uint timestamp
    ) external view returns (uint256 averageWeight);

    function tokensOfOwner(
        address owner
    ) external view returns (uint256[] memory);

    function voting(address user, uint256 proposalId) external;

    function abstain(address user) external;
}

File 18 of 19 : IVePostNFTSVG.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

interface IVePostNFTSVG {
    function buildVePost(
        uint256 tokenId,
        uint8 typeVePost, // 0: Token, 1: LP NFT
        uint256 startTimeLock,
        uint256 endTimeLock,
        uint256 currentTime,
        uint256 boost,
        uint256 currentWeight
    ) external view returns (string memory);
}

File 19 of 19 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

library console {
    address constant CONSOLE_ADDRESS =
        0x000000000000000000636F6e736F6c652e6c6f67;

    function _sendLogPayloadImplementation(bytes memory payload) internal view {
        address consoleAddress = CONSOLE_ADDRESS;
        /// @solidity memory-safe-assembly
        assembly {
            pop(
                staticcall(
                    gas(),
                    consoleAddress,
                    add(payload, 32),
                    mload(payload),
                    0,
                    0
                )
            )
        }
    }

    function _castToPure(
      function(bytes memory) internal view fnIn
    ) internal pure returns (function(bytes memory) pure fnOut) {
        assembly {
            fnOut := fnIn
        }
    }

    function _sendLogPayload(bytes memory payload) internal pure {
        _castToPure(_sendLogPayloadImplementation)(payload);
    }

    function log() internal pure {
        _sendLogPayload(abi.encodeWithSignature("log()"));
    }
    function logInt(int256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
    }

    function logUint(uint256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
    }

    function logString(string memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function logBool(bool p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function logAddress(address p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function logBytes(bytes memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
    }

    function logBytes1(bytes1 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
    }

    function logBytes2(bytes2 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
    }

    function logBytes3(bytes3 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
    }

    function logBytes4(bytes4 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
    }

    function logBytes5(bytes5 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
    }

    function logBytes6(bytes6 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
    }

    function logBytes7(bytes7 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
    }

    function logBytes8(bytes8 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
    }

    function logBytes9(bytes9 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
    }

    function logBytes10(bytes10 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
    }

    function logBytes11(bytes11 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
    }

    function logBytes12(bytes12 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
    }

    function logBytes13(bytes13 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
    }

    function logBytes14(bytes14 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
    }

    function logBytes15(bytes15 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
    }

    function logBytes16(bytes16 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
    }

    function logBytes17(bytes17 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
    }

    function logBytes18(bytes18 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
    }

    function logBytes19(bytes19 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
    }

    function logBytes20(bytes20 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
    }

    function logBytes21(bytes21 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
    }

    function logBytes22(bytes22 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
    }

    function logBytes23(bytes23 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
    }

    function logBytes24(bytes24 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
    }

    function logBytes25(bytes25 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
    }

    function logBytes26(bytes26 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
    }

    function logBytes27(bytes27 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
    }

    function logBytes28(bytes28 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
    }

    function logBytes29(bytes29 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
    }

    function logBytes30(bytes30 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
    }

    function logBytes31(bytes31 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
    }

    function logBytes32(bytes32 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
    }

    function log(uint256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
    }

    function log(string memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function log(bool p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function log(address p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function log(uint256 p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
    }

    function log(uint256 p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
    }

    function log(uint256 p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
    }

    function log(uint256 p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
    }

    function log(string memory p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
    }

    function log(string memory p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
    }

    function log(string memory p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
    }

    function log(string memory p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
    }

    function log(bool p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
    }

    function log(bool p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
    }

    function log(bool p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
    }

    function log(bool p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
    }

    function log(address p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
    }

    function log(address p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
    }

    function log(address p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
    }

    function log(address p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
    }

    function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
    }

    function log(string memory p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
    }

    function log(string memory p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
    }

    function log(string memory p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
    }

    function log(string memory p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
    }

    function log(bool p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
    }

    function log(bool p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
    }

    function log(bool p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
    }

    function log(bool p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
    }

    function log(bool p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
    }

    function log(bool p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
    }

    function log(bool p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
    }

    function log(bool p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
    }

    function log(address p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
    }

    function log(address p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
    }

    function log(address p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
    }

    function log(address p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
    }

    function log(address p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
    }

    function log(address p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
    }

    function log(address p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
    }

    function log(address p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
    }

    function log(address p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
    }

    function log(address p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
    }

    function log(address p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
    }

    function log(address p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
    }

}

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

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"token_addr","type":"address"},{"internalType":"address","name":"_lpNft","type":"address"},{"internalType":"address","name":"_vePostNFTSVG","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"locktime","type":"uint256"},{"indexed":false,"internalType":"enum VePost.DepositType","name":"deposit_type","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"BASE_PERCENT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"abstain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"averageMultiWeightInTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"averageWeightInTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"balanceOfAtNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"balanceOfNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_t","type":"uint256"}],"name":"balanceOfNFTAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostLPNft","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostMultiplier","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostToken","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferTimeToCalAverageWeight","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"}],"name":"create_lock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"create_lock_for","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uni_lp_token_id","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"}],"name":"create_lock_nft_lp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uni_lp_token_id","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"create_lock_nft_lp_for","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"deposit_for","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getAverageWeightOfOwner","outputs":[{"internalType":"uint256","name":"averageWeight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getTotalWeightOfOwner","outputs":[{"internalType":"uint256","name":"totalWeight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"get_last_user_slope","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"handlers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"increase_amount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_lock_duration","type":"uint256"}],"name":"increase_unlock_time","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isLockVeWhenStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockType","outputs":[{"internalType":"enum VePost.LockType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"lockWhenStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint32","name":"boostMultiplier","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"locked__end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpNft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownership_change","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readerUniSwapPosition","outputs":[{"internalType":"contract IReaderUniSwapPosition","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revenueShares","outputs":[{"internalType":"contract IRevenueShares","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_boostLPNft","type":"uint32"}],"name":"setBoostLPNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_boostMultiplier","type":"uint32"}],"name":"setBoostMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_boostToken","type":"uint32"}],"name":"setBoostToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_bufferTimeToCalAverageWeight","type":"uint32"}],"name":"setBufferTimeToCalAverageWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_handler","type":"address"},{"internalType":"bool","name":"isHandler","type":"bool"}],"name":"setHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lpNft","type":"address"}],"name":"setLPNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_readerUniSwapPosition","type":"address"}],"name":"setReaderUniSwapPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_revenueShares","type":"address"}],"name":"setRevenueShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vePostSVG","type":"address"}],"name":"setVePostSVG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_voter","type":"address"}],"name":"setVoter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"shuttleRevenueTracking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slope_changes","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_tokenIndex","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"t","type":"uint256"}],"name":"tokensDetailOfOwner","outputs":[{"components":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint32","name":"boostMultiplier","type":"uint32"},{"internalType":"enum VePost.LockType","name":"lockType","type":"uint8"},{"internalType":"uint256","name":"currentWeight","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct VePost.VePostDetail[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"t","type":"uint256"}],"name":"totalSupplyAtT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unLockWhenStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"user_point_history__ts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vePostNFTSVG","outputs":[{"internalType":"contract IVePostNFTSVG","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vePostToLPNft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"voting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"votingProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whiteListContractPostTech","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a0604052601180547d3a9800002ee000004e2000000000000000000000000000000000000000006001600160a01b039091161790556012805463ffffffff19166203f480179055612710601555601d805460ff191660011790553480156200006757600080fd5b50604051620055d3380380620055d38339810160408190526200008a9162000293565b3380620000b157604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000bc8162000226565b506001600160a01b03838116608052600e8054336001600160a01b03199182161790915560148054821684841617905560118054909116918416919091179055620001044390565b7f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746be55427f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bd55601c6020527fb0c25367d01b0b781361644d24351498497c7f5fda75b6c0d47e4fdd049ac8a0805460ff1990811660019081179092557ff595234eda6c0db1c0584402658ad719acc19e7c8766077cf14fcd1f75de2b488054821683179055635b5e139f60e01b60009081527ffeb1ffba76aed7ef63c1399281f553b63d323c070594bef356272f7cf8f0422e8054909216909217905560155460405190913091600080516020620055b3833981519152908290a46015546040516000903090600080516020620055b3833981519152908390a4505050620002dd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200028e57600080fd5b919050565b600080600060608486031215620002a957600080fd5b620002b48462000276565b9250620002c46020850162000276565b9150620002d46040850162000276565b90509250925092565b6080516152ac6200030760003960008181610d9601528181612fa20152613c7a01526152ac6000f3fe608060405234801561001057600080fd5b50600436106104cd5760003560e01c8063869d2efc11610283578063bcebc7831161015c578063e7ac6b46116100ce578063ee99fe2811610092578063ee99fe2814610d1b578063f17156a714610d2e578063f2fde38b14610d41578063f6f518c614610d54578063f8a0576314610d6e578063fc0c546a14610d9157600080fd5b8063e7ac6b4614610c93578063e7e242d414610ca6578063e985e9c514610cb9578063ec36b40514610cf5578063ee552e3b14610d0857600080fd5b8063c87b56dd11610120578063c87b56dd14610be5578063d1febfb914610bf8578063d4e54c3b14610c36578063dacff02514610c49578063e0514aba14610c60578063e441135c14610c7357600080fd5b8063bcebc78314610b87578063c1e9cf9814610ba7578063c28b21f014610bba578063c2c4c5c114610bca578063c3b502e914610bd257600080fd5b80639cb7de4b116101f5578063a4d855df116101b9578063a4d855df14610aab578063aa33ac8114610abe578063aec2ccae14610ad1578063b45a3c0e14610af4578063b513ec9914610b61578063b88d4fde14610b7457600080fd5b80639cb7de4b14610a485780639d65e31114610a5b578063a003aac414610a6e578063a183af5214610a85578063a22cb46514610a9857600080fd5b8063900cf0cf11610247578063900cf0cf146109c15780639360b8dd146109ca57806395d89b41146109dd57806397518e0e14610a025780639782bebb14610a22578063981b24d014610a3557600080fd5b8063869d2efc146109645780638c2c9baf146109775780638da5cb5b1461098a5780638f7239e71461099b5780639007d70e146109ae57600080fd5b806342842e0e116103b55780636352211e116103275780637116c60c116102eb5780637116c60c146108d057806371197484146108e3578063715018a614610906578063719c98e21461090e578063722d7a07146109315780638462151c1461094457600080fd5b80636352211e1461083157806365fc38731461085a57806368bcc3fd1461086d5780636f5488371461089d57806370a08231146108bd57600080fd5b80635266d753116103795780635266d7531461079b57806354fd4d50146107be578063568e20f0146107e257806359c1a087146107f557806362431a5f1461080857806362f3765e1461082857600080fd5b806342842e0e14610729578063430c20811461073c578063461f711c1461074f57806346c96aac146107755780634bc2a6571461078857600080fd5b806323b872dd1161044e578063313ce56711610412578063313ce567146106a2578063329a8cfa146106bc578063379df6e1146106c45780633a589b97146106d75780633e00a8a414610703578063410509cf1461071657600080fd5b806323b872dd1461064357806323d304fc146106565780632e1a7d4d146106695780632f558a8f1461067c5780632f745c591461068f57600080fd5b8063136419931161049557806313641993146105b75780631376f3da146105ca57806318160ddd146106055780631a21c0bc1461060d5780631c984bc31461063057600080fd5b806301ffc9a7146104d2578063047fc9aa1461051457806306fdde031461052b578063081812fc14610561578063095ea7b3146105a2575b600080fd5b6104ff6104e03660046148fa565b6001600160e01b0319166000908152601c602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61051d60015481565b60405190815260200161050b565b6105546040518060400160405280600a8152602001691d99541bdcdd0813919560b21b81525081565b60405161050b9190614967565b61058a61056f36600461497a565b6000908152601760205260409020546001600160a01b031690565b6040516001600160a01b03909116815260200161050b565b6105b56105b03660046149af565b610db8565b005b6105b56105c536600461497a565b610ea0565b6105dd6105d83660046149d9565b610ef3565b60408051600f95860b81529390940b602084015292820152606081019190915260800161050b565b61051d610f3b565b6104ff61061b3660046149fb565b600d6020526000908152604090205460ff1681565b61051d61063e3660046149d9565b610f4b565b6105b5610651366004614a16565b610f7f565b6105b56106643660046149fb565b610f90565b6105b561067736600461497a565b610fba565b6105b561068a3660046149af565b610ff3565b61051d61069d3660046149af565b611069565b6106aa601281565b60405160ff909116815260200161050b565b6105b5611091565b6105b56106d23660046149fb565b61109c565b6011546106ee90600160c01b900463ffffffff1681565b60405163ffffffff909116815260200161050b565b6105b5610711366004614a52565b6110c6565b6105b561072436600461497a565b61114c565b6105b5610737366004614a16565b6111a0565b6104ff61074a3660046149af565b6111bb565b61076261075d36600461497a565b6111ce565b604051600f9190910b815260200161050b565b600e5461058a906001600160a01b031681565b6105b56107963660046149fb565b611212565b6104ff6107a93660046149fb565b60096020526000908152604090205460ff1681565b610554604051806040016040528060058152602001640312e302e360dc1b81525081565b61051d6107f03660046149af565b61123c565b6105b5610803366004614a52565b6112b4565b61081b6108163660046149af565b611339565b60405161050b9190614aa2565b6106ee61271081565b61058a61083f36600461497a565b6000908152601660205260409020546001600160a01b031690565b61051d6108683660046149d9565b611531565b61089061087b36600461497a565b600b6020526000908152604090205460ff1681565b60405161050b9190614b3d565b61051d6108ab36600461497a565b60036020526000908152604090205481565b61051d6108cb3660046149fb565b611575565b61051d6108de36600461497a565b611593565b6107626108f136600461497a565b600860205260009081526040902054600f0b81565b6105b56115f3565b6104ff61091c36600461497a565b600c6020526000908152604090205460ff1681565b6105b561093f3660046149fb565b611605565b6109576109523660046149fb565b61163a565b60405161050b9190614b4b565b6105b561097236600461497a565b6116e8565b61051d6109853660046149d9565b61177f565b6000546001600160a01b031661058a565b6105b56109a9366004614a52565b61178b565b6105b56109bc3660046149fb565b6117af565b61051d60045481565b61051d6109d8366004614b8f565b611800565b610554604051806040016040528060068152602001651d995413d4d560d21b81525081565b61051d610a103660046149fb565b60106020526000908152604090205481565b60135461058a906001600160a01b031681565b61051d610a4336600461497a565b6118d8565b6105b5610a56366004614bc9565b611a70565b61051d610a693660046149af565b611aa3565b6011546106ee90600160a01b900463ffffffff1681565b6105b5610a933660046149d9565b611b2c565b6105b5610aa6366004614bc9565b611dba565b6105b5610ab93660046149d9565b611e3e565b61051d610acc366004614c00565b61208b565b6104ff610adf3660046149fb565b600f6020526000908152604090205460ff1681565b610b36610b0236600461497a565b60026020819052600091825260409091208054600182015492820154600390920154600f9190910b92919063ffffffff1684565b60408051600f9590950b855260208501939093529183015263ffffffff16606082015260800161050b565b61051d610b6f366004614c7c565b612206565b6105b5610b82366004614d5a565b61237f565b61051d610b9536600461497a565b600a6020526000908152604090205481565b6105b5610bb5366004614a52565b6124ad565b6012546106ee9063ffffffff1681565b6105b56124db565b60145461058a906001600160a01b031681565b610554610bf336600461497a565b612541565b6105dd610c0636600461497a565b600560205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b61051d610c44366004614c00565b6126e4565b6011546106ee90600160e01b900463ffffffff1681565b61051d610c6e3660046149d9565b612729565b61051d610c8136600461497a565b60076020526000908152604090205481565b6105b5610ca136600461497a565b612735565b61051d610cb436600461497a565b61277c565b6104ff610cc7366004614e05565b6001600160a01b039182166000908152601b6020908152604080832093909416825291909152205460ff1690565b61051d610d033660046149d9565b6127a5565b6105b5610d163660046149fb565b61291f565b6105b5610d293660046149d9565b612949565b60115461058a906001600160a01b031681565b6105b5610d4f3660046149fb565b612b46565b60125461058a90600160201b90046001600160a01b031681565b61051d610d7c36600461497a565b60009081526002602052604090206001015490565b61058a7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152601660205260409020546001600160a01b031680610dda57600080fd5b806001600160a01b0316836001600160a01b031603610df857600080fd5b6000828152601660209081526040808320546001600160a01b038581168552601b845282852033808752945291909320549216149060ff168180610e395750805b610e4257600080fd5b60008481526017602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b336000908152600d602052604090205460ff16610ed85760405162461bcd60e51b8152600401610ecf90614e38565b60405180910390fd5b6000908152600c60205260409020805460ff19166001179055565b6006602052816000526040600020816402540be4008110610f1357600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610f4642611593565b905090565b6000828152600660205260408120826402540be4008110610f6e57610f6e614e5e565b600302016001015490505b92915050565b610f8b83838333612b81565b505050565b610f98612cff565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b601d5460ff16600114610fcc57600080fd5b601d805460ff19166002179055610fe38133612d2c565b50601d805460ff19166001179055565b600e546001600160a01b031633146110385760405162461bcd60e51b815260206004820152600860248201526737b7363c9023b7bb60c11b6044820152606401610ecf565b6001600160a01b039091166000908152600f60209081526040808320805460ff191660011790556010909152902055565b6001600160a01b03919091166000908152601960209081526040808320938352929052205490565b61109a33613155565b565b6110a4612cff565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b6110ce612cff565b61271063ffffffff821610156111265760405162461bcd60e51b815260206004820152601f60248201527f626f6f7374546f6b656e206d757374203e3d20424153455f50455243454e54006044820152606401610ecf565b6011805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b601d5460ff1660011461115e57600080fd5b601d805460ff191660021790556000818152601660205260408120546001600160a01b0316905061118f8282612d2c565b5050601d805460ff19166001179055565b610f8b8383836040518060200160405280600081525061237f565b60006111c78383613233565b9392505050565b60008181526007602090815260408083205460069092528220816402540be40081106111fc576111fc614e5e565b6003020154600160801b9004600f0b9392505050565b61121a612cff565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000806112488461163a565b9050805160000361125d576000915050610f79565b82600003611269574292505b60005b81518110156112ac5761129882828151811061128a5761128a614e5e565b602002602001015185612729565b6112a29084614e8a565b925060010161126c565b505092915050565b6112bc612cff565b61271063ffffffff821610156113145760405162461bcd60e51b815260206004820181905260248201527f5f626f6f73744c504e6674206d757374203e3d20424153455f50455243454e546044820152606401610ecf565b6011805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b6060600061135c846001600160a01b031660009081526018602052604090205490565b905060008167ffffffffffffffff81111561137957611379614c35565b6040519080825280602002602001820160405280156113ea57816020015b6113d76040805160e08101825260008082526020820181905291810182905260608101829052906080820190815260200160008152602001600081525090565b8152602001906001900390816113975790505b50604080516080810182526000808252602082018190529181018290526060810182905291925090600086600003611420574296505b60005b85811015611524576114358982611069565b60008181526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff166060820152909450925061148b8489613299565b6040805160e08101825285516001600160801b0316815260208087015181830152868301518284015260608088015163ffffffff16908301526000888152600b909152919091205491935090608082019060ff1660028111156114f0576114f0614a78565b81526020018381526020018581525085828151811061151157611511614e5e565b6020908102919091010152600101611423565b5092979650505050505050565b601d5460009060ff1660011461154657600080fd5b601d805460ff191660021790556115608383336001613375565b9050601d805460ff1916600117905592915050565b6001600160a01b038116600090815260186020526040812054610f79565b600454600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906115eb81856135e0565b949350505050565b6115fb612cff565b61109a60006136d9565b61160d612cff565b601280546001600160a01b03909216600160201b02640100000000600160c01b0319909216919091179055565b6060600061165d836001600160a01b031660009081526018602052604090205490565b905060008167ffffffffffffffff81111561167a5761167a614c35565b6040519080825280602002602001820160405280156116a3578160200160208202803683370190505b50905060005b828110156116e0576116bb8582611069565b8282815181106116cd576116cd614e5e565b60209081029190910101526001016116a9565b509392505050565b336000908152600d602052604090205460ff166117175760405162461bcd60e51b8152600401610ecf90614e38565b601254604051635d7d9d2b60e11b815260048101839052600160201b9091046001600160a01b03169063bafb3a56906024015b600060405180830381600087803b15801561176457600080fd5b505af1158015611778573d6000803e3d6000fd5b5050505050565b60006111c78383613729565b611793612cff565b6012805463ffffffff191663ffffffff92909216919091179055565b600e546001600160a01b031633146117f45760405162461bcd60e51b815260206004820152600860248201526737b7363c9023b7bb60c11b6044820152606401610ecf565b6117fd81613155565b50565b600083815260026020818152604080842081516080810183528154600f0b8152600182015493810184905293810154918401919091526003015463ffffffff16606083015283111561188357601254602082015163ffffffff909116906118679085614e9d565b10156118795780602001519250611883565b60009150506111c7565b8284118061189357508051600f0b155b156118a25760009150506111c7565b600060026118b08786613299565b6118ba8888613299565b6118c49190614e8a565b6118ce9190614ec6565b9695505050505050565b6000438211156118ea576118ea614eda565b60045460006118f98483613a02565b600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925083831015611a0857600060058161195c866001614e8a565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905285015191925014611a0257826060015181606001516119c89190614e9d565b836040015182604001516119dc9190614e9d565b60608501516119eb908a614e9d565b6119f59190614ef0565b6119ff9190614ec6565b91505b50611a57565b43826060015114611a57576060820151611a229043614e9d565b6040830151611a319042614e9d565b6060840151611a409089614e9d565b611a4a9190614ef0565b611a549190614ec6565b90505b6118ce82828460400151611a6b9190614e8a565b6135e0565b611a78612cff565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b6000806000611ab18561163a565b90508051600003611ac757600092505050610f79565b83600003611ad3574293505b60005b8151811015611b1657611b02828281518110611af457611af4614e5e565b602002602001015186612729565b611b0c9084614e8a565b9250600101611ad6565b508051611b239083614ec6565b95945050505050565b601d5460ff16600114611b3e57600080fd5b601d805460ff19166002179055611b553383613233565b611b715760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615611ba05760405162461bcd60e51b8152600401610ecf90614f33565b6000828152600a602052604090205415611bfc5760405162461bcd60e51b815260206004820152601a60248201527f4d757374206e6f7420697320756e6953776170206e6674206c700000000000006044820152606401610ecf565b60008281526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff16606082015281611c815760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610ecf565b60008160000151600f0b13611cd15760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610ecf565b42816020015111611cf45760405162461bcd60e51b8152600401610ecf90614f6a565b601260049054906101000a90046001600160a01b03166001600160a01b03166304650cbd3385858560000151611d2a9190614fae565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526001600160801b03166044820152606401600060405180830381600087803b158015611d8157600080fd5b505af1158015611d95573d6000803e3d6000fd5b50505050611da883836000846003613a80565b5050601d805460ff1916600117905550565b336001600160a01b03831603611dd257611dd2614eda565b336000818152601b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b601d5460ff16600114611e5057600080fd5b601d805460ff19166002179055611e673383613233565b611e835760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615611eb25760405162461bcd60e51b8152600401610ecf90614f33565b600082815260026020818152604080842081516080810183528154600f0b8152600182015493810193909352928301549082015260039091015463ffffffff1660608201529062093a8080611f078542614e8a565b611f119190614ec6565b611f1b9190614ef0565b905042826020015111611f5f5760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610ecf565b60008260000151600f0b13611faa5760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610ecf565b81602001518111611ffd5760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610ecf565b61200b630784ce0042614e8a565b81111561205a5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610ecf565b42604083015261206933613da4565b61207884600083856004613a80565b5050601d805460ff191660011790555050565b601d5460009060ff166001146120a057600080fd5b601d805460ff191660021790556013546040516313421d2b60e31b8152600481018690526000916001600160a01b031690639a10e958906024016040805180830381865afa1580156120f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211a9190614fce565b509050600081116121685760405162461bcd60e51b8152602060048201526018602482015277139bc81c1bdcdd08185b5bdd5b9d081a5b8813140813919560421b6044820152606401610ecf565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd9061219c90339030908a90600401614ff2565b600060405180830381600087803b1580156121b657600080fd5b505af11580156121ca573d6000803e3d6000fd5b5050505060006121dd8286866002613375565b6000818152600a6020526040902087905592505050601d805460ff191660011790559392505050565b60008080805b865181101561235d5760006002600089848151811061222d5761222d614e5e565b6020908102919091018101518252818101929092526040908101600090812082516080810184528154600f0b8082526001830154958201959095526002820154938101939093526003015463ffffffff166060830152909250036122915750612355565b8261229b81615016565b93505080602001518611156122dd57601254602082015163ffffffff909116906122c59088614e9d565b10156122d757806020015195506122dd565b50612355565b60008688101561234657600261230c8a85815181106122fe576122fe614e5e565b602002602001015189613299565b61232f8b868151811061232157612321614e5e565b60200260200101518b613299565b6123399190614e8a565b6123439190614ec6565b90505b6123508186614e8a565b945050505b60010161220c565b5080156123735761236e8183614ec6565b6118ce565b60009695505050505050565b61238b84848433612b81565b823b156124a757604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906123c490339088908790879060040161502f565b6020604051808303816000875af19250505080156123ff575060408051601f3d908101601f191682019092526123fc91810190615062565b60015b611778573d80801561242d576040519150601f19603f3d011682016040523d82523d6000602084013e612432565b606091505b50805160000361249f5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610ecf565b805181602001fd5b50505050565b6124b5612cff565b6011805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61109a600060405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff1681525060405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff16815250613de1565b6000818152601660205260409020546060906001600160a01b03166125a85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610ecf565b600082815260026020818152604080842081516080810183528154600f0b815260018083015482860152828601548285015260039092015463ffffffff166060820152601454888752600b909452919094205490936001600160a01b03909216926353dd3389928792909160ff9091169081111561262857612628614a78565b14612634576002612637565b60015b604085015160208601514260608801516126518b42613299565b6040516001600160e01b031960e08a901b168152600481019790975260ff909516602487015260448601939093526064850191909152608484015263ffffffff1660a483015260c482015260e401600060405180830381865afa1580156126bc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111c7919081019061507f565b601d5460009060ff166001146126f957600080fd5b601d805460ff191660021790556127138484846001613375565b9050601d805460ff191660011790559392505050565b60006111c78383613299565b336000908152600d602052604090205460ff166127645760405162461bcd60e51b8152600401610ecf90614e38565b6000908152600c60205260409020805460ff19169055565b6000436000838152600360205260409020540361279b57506000919050565b610f798242613299565b601d5460009060ff166001146127ba57600080fd5b601d805460ff191660021790556013546040516313421d2b60e31b8152600481018590526000916001600160a01b031690639a10e958906024016040805180830381865afa158015612810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128349190614fce565b509050600081116128825760405162461bcd60e51b8152602060048201526018602482015277139bc81c1bdcdd08185b5bdd5b9d081a5b8813140813919560421b6044820152606401610ecf565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906128b690339030908990600401614ff2565b600060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b5050505060006128f78285336002613375565b6000818152600a6020526040902086905592505050601d805460ff1916600117905592915050565b612927612cff565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b601d5460ff1660011461295b57600080fd5b601d805460ff1916600290811790915560008381526020828152604080832081516080810183528154600f0b815260018201548185015294810154858301526003015463ffffffff166060850152858352600a90915290205415612a015760405162461bcd60e51b815260206004820152601a60248201527f4d757374206e6f7420697320756e6953776170206e6674206c700000000000006044820152606401610ecf565b60008211612a0e57600080fd5b60008160000151600f0b13612a5e5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610ecf565b42816020015111612a815760405162461bcd60e51b8152600401610ecf90614f6a565b6012546001600160a01b03600160201b909104166304650cbd612ab9856000908152601660205260409020546001600160a01b031690565b83518690612ac8908790614fae565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526001600160801b03166044820152606401600060405180830381600087803b158015612b1f57600080fd5b505af1158015612b33573d6000803e3d6000fd5b50505050611da883836000846000613a80565b612b4e612cff565b6001600160a01b038116612b7857604051631e4fbdf760e01b815260006004820152602401610ecf565b6117fd816136d9565b612b8a84613155565b6001600160a01b0384166000908152600f602052604090205460ff1615612be55760405162461bcd60e51b815260206004820152600f60248201526e746f6b656e20696e20766f74696e6760881b6044820152606401610ecf565b6015546000908152600c602052604090205460ff1615612c405760405162461bcd60e51b815260206004820152601660248201527536bab9ba103737ba103637b1b5903a3930b739b332b960511b6044820152606401610ecf565b612c4a8183613233565b612c885760405162461bcd60e51b815260206004820152600f60248201526e2737ba1037bbb732b9103a37b5b2b760891b6044820152606401610ecf565b612c93848484614419565b612c9d84836144d1565b612ca78483614538565b612cb183836145b9565b6000828152600360205260408082204390555183916001600160a01b0386811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000546001600160a01b0316331461109a5760405163118cdaa760e01b8152336004820152602401610ecf565b612d368183613233565b612d525760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615612d815760405162461bcd60e51b8152600401610ecf90614f33565b6000828152601660205260409020546001600160a01b0316612da281613155565b6001600160a01b0381166000908152600f602052604090205460ff1615612dfd5760405162461bcd60e51b815260206004820152600f60248201526e746f6b656e20696e20766f74696e6760881b6044820152606401610ecf565b612e07828461464f565b60008381526002602081815260409283902083516080810185528154600f0b81526001820154928101839052928101549383019390935260039092015463ffffffff16606082015290421015612e985760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610ecf565b80516040805160808101825260008082526020808301828152838501838152606085018481528b855260029384905295909320935184546001600160801b0319166001600160801b039091161784555160018085019190915591519083015591516003909101805463ffffffff191663ffffffff90921691909117905554600f9190910b90612f278282614e9d565b600181905550612f65868460405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff16815250613de1565b6000868152600a6020526040812054908190036130205760405163a9059cbb60e01b81526001600160a01b038781166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300f91906150ed565b61301b5761301b614eda565b613096565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906130549030908a908690600401614ff2565b600060405180830381600087803b15801561306e57600080fd5b505af1158015613082573d6000803e3d6000fd5b5050506000888152600a6020526040812055505b6000878152600b60205260409020805460ff191690556130b5876146c2565b6001600160a01b0386167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948885426040805193845260208401929092529082015260600160405180910390a27f21e69d6eb75b6c23bbc769d20f147b2d4bd10ffdaef330c7bf634c2686302fa78261312d8582614e9d565b426040805193845260208401929092529082015260600160405180910390a150505050505050565b6001600160a01b0381166000908152601060205260408120549081900361317a575050565b600e54604051631f27a4f360e11b8152600481018390526000916001600160a01b031690633e4f49e690602401602060405180830381865afa1580156131c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e8919061510a565b905060018160078111156131fe576131fe614a78565b14610f8b57610f8b836001600160a01b03166000908152600f60209081526040808320805460ff191690556010909152812055565b60008181526016602090815260408083205460178352818420546001600160a01b03918216808652601b855283862088841680885295529285205492938085149392909116149060ff1682806132865750815b8061328e5750805b979650505050505050565b6000828152600760205260408120548082036132b9576000915050610f79565b6000848152600660205260408120826402540be40081106132dc576132dc614e5e565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150613328908561512b565b8160200151613337919061514b565b8151829061334690839061516b565b600f90810b90915282516000910b1215905061336157600081525b51600f0b9150610f799050565b5092915050565b60008062093a80806133878742614e8a565b6133919190614ec6565b61339b9190614ef0565b9050600086116133dd5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b6044820152606401610ecf565b42811161343b5760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610ecf565b613449630784ce0042614e8a565b8111156134985760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610ecf565b6276a7008510156134eb5760405162461bcd60e51b815260206004820152601d60248201527f566f74696e67206c6f636b206d7573742033206d6f6e746873206d696e0000006044820152606401610ecf565b6015600081546134fa90615016565b9091555060155461350b8582614781565b50600284600481111561352057613520614a78565b03613543576000818152600b60205260409020805460ff19166002179055613576565b600184600481111561355757613557614a78565b03613576576000818152600b60205260409020805460ff191660011790555b61357f85613da4565b60008181526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff1660608201526135d69082908990859088613a80565b6118ce85826147e4565b600080839050600062093a808083604001516135fc9190614ec6565b6136069190614ef0565b905060005b60ff8110156136b15761362162093a8083614e8a565b915060008583111561363557859250613649565b50600082815260086020526040902054600f0b5b60408401516136589084614e9d565b8460200151613667919061514b565b8451859061367690839061516b565b600f0b90525085830361368957506136b1565b808460200181815161369b9190615198565b600f0b905250506040830182905260010161360b565b5060008260000151600f0b12156136c757600082525b50516001600160801b03169392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60004382111561373b5761373b614eda565b600083815260076020526040812054815b60808110156137d457818310156137d4576000600261376b8486614e8a565b613776906001614e8a565b6137809190614ec6565b60008881526006602052604090209091508690826402540be40081106137a8576137a8614e5e565b6003020160020154116137bd578093506137cb565b6137c8600182614e9d565b92505b5060010161374c565b506000858152600660205260408120836402540be40081106137f8576137f8614e5e565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152600454909150600061384d8783613a02565b600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561392c5760006005816138b1876001614e8a565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061390e9190614e9d565b9250836040015181604001516139249190614e9d565b915050613956565b606083015161393b9043614e9d565b915082604001516139494290565b6139539190614e9d565b90505b60408301518215613993578284606001518c6139729190614e9d565b61397c9084614ef0565b6139869190614ec6565b6139909082614e8a565b90505b60408701516139a29082614e9d565b87602001516139b1919061514b565b875188906139c090839061516b565b600f90810b90915288516000910b1290506139f057505093516001600160801b03169650610f7995505050505050565b60009950505050505050505050610f79565b60008082815b6080811015613a765781831015613a765760006002613a278486614e8a565b613a32906001614e8a565b613a3c9190614ec6565b6000818152600560205260409020600201549091508710613a5f57809350613a6d565b613a6a600182614e9d565b92505b50600101613a08565b5090949350505050565b6001548290613a8f8682614e8a565b600155604080516080810182526000808252602080830182815293830182905260608084019283528651918701519087015163ffffffff169092529252600f9190910b8152825187908490613ae5908390615198565b600f0b9052508515613af957602083018690525b8260400151600003613b0c574260408401525b826060015163ffffffff16600003613bd1576127106002856004811115613b3557613b35614a78565b03613b725760115461271090613b619063ffffffff600160a01b8204811691600160e01b9004166151c5565b613b6b91906151e5565b9050613bbf565b6001856004811115613b8657613b86614a78565b03613bbf5760115461271090613bb29063ffffffff600160a01b8204811691600160c01b9004166151c5565b613bbc91906151e5565b90505b63ffffffff1660608083018290528401525b600088815260026020818152604092839020865181546001600160801b0319166001600160801b03909116178155908601516001820155918501519082015560608401516003909101805463ffffffff191663ffffffff909216919091179055613c3c888285613de1565b338715801590613c5e57506002856004811115613c5b57613c5b614a78565b14155b15613d02576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613cb390849030908d90600401614ff2565b6020604051808303816000875af1158015613cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf691906150ed565b613d0257613d02614eda565b60208401516001600160a01b0382167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b8942604051613d469493929190615208565b60405180910390a37f21e69d6eb75b6c23bbc769d20f147b2d4bd10ffdaef330c7bf634c2686302fa783613d7a8a82614e8a565b426040805193845260208401929092529082015260600160405180910390a1505050505050505050565b6012546040516001623d2ea360e11b031981526001600160a01b038381166004830152600160201b9092049091169063ff85a2ba9060240161174a565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260045460009081908715613f8257428760200151118015613e51575060008760000151600f0b135b15613eb157613e66612710630784ce0061514b565b87516060890151613e7a919060030b61514b565b613e849190615238565b600f0b6020860152428760200151613e9c9190614e9d565b8560200151613eab919061514b565b600f0b85525b428660200151118015613ecb575060008660000151600f0b135b15613f2b57613ee0612710630784ce0061514b565b86516060880151613ef4919060030b61514b565b613efe9190615238565b600f0b6020850152428660200151613f169190614e9d565b8460200151613f25919061514b565b600f0b84525b602080880151600090815260088252604090205490870151600f9190910b935015613f82578660200151866020015103613f6757829150613f82565b602080870151600090815260089091526040902054600f0b91505b604080516080810182526000808252602082015242918101919091524360608201528115613ff7575060008181526005602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000824211156140445760408401516140169042614e9d565b60608501516140259043614e9d565b61403790670de0b6b3a7640000614ef0565b6140419190614ec6565b90505b600062093a806140548186614ec6565b61405e9190614ef0565b905060005b60ff8110156141d05761407962093a8083614e8a565b915060004283111561408d574292506140a1565b50600082815260086020526040902054600f0b5b6140ab8684614e9d565b87602001516140ba919061514b565b875188906140c990839061516b565b600f0b9052506020870180518291906140e3908390615198565b600f90810b90915288516000910b121590506140fe57600087525b60008760200151600f0b121561411657600060208801525b60408088018490528501519295508592670de0b6b3a76400009061413a9085614e9d565b6141449086614ef0565b61414e9190614ec6565b856060015161415d9190614e8a565b606088015261416d600189614e8a565b975042830361418257436060880152506141d0565b6000888152600560209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550600101614063565b505060048590558b1561425b57886020015188602001516141f1919061516b565b846020018181516142029190615198565b600f0b90525088518851614216919061516b565b84518590614225908390615198565b600f90810b90915260208601516000910b1215905061424657600060208501525b60008460000151600f0b121561425b57600084525b6000858152600560209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b1561440b57428b6020015111156143125760208901516142c19088615198565b96508a602001518a60200151036142e45760208801516142e1908861516b565b96505b60208b810151600090815260089091526040902080546001600160801b0319166001600160801b0389161790555b428a60200151111561436d578a602001518a60200151111561436d57602088015161433d908761516b565b60208b810151600090815260089091526040902080546001600160801b0319166001600160801b03831617905595505b60008c815260076020526040812054614387906001614e8a565b60008e815260076020526040902081905590504260408a01524360608a015260008d81526006602052604090208990826402540be40081106143cb576143cb614e5e565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b6001600160a01b03821660009081526009602052604090205460ff1615801561445b57506001600160a01b03831660009081526009602052604090205460ff16155b15610f8b57601254604051633b6a328960e11b8152600160201b9091046001600160a01b0316906376d465129061449a90869086908690600401614ff2565b600060405180830381600087803b1580156144b457600080fd5b505af11580156144c8573d6000803e3d6000fd5b50505050505050565b6000818152601660205260409020546001600160a01b038381169116146144fa576144fa614eda565b6000818152601760205260409020546001600160a01b03161561453457600081815260176020526040902080546001600160a01b03191690555b5050565b6000818152601660205260409020546001600160a01b0383811691161461456157614561614eda565b600081815260166020526040902080546001600160a01b03191690556145878282614825565b6001600160a01b03821660009081526018602052604081208054600192906145b0908490614e9d565b90915550505050565b6000818152601660205260409020546001600160a01b0316156145de576145de614eda565b600081815260166020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260188084528285208054601986528487208188528652848720889055878752601a8652938620939093559084529091528054600192906145b0908490614e8a565b601254604051633c3ad31960e01b81526001600160a01b03848116600483015260248201849052600160201b90920490911690633c3ad319906044015b600060405180830381600087803b1580156146a657600080fd5b505af11580156146ba573d6000803e3d6000fd5b505050505050565b6146cc3382613233565b6147185760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610ecf565b6000818152601660205260408120546001600160a01b03169061473b9083610db8565b6147453383614538565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60006001600160a01b03831661479957614799614eda565b6147a383836145b9565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b601254604051631e573fb760e31b81526001600160a01b03848116600483015260248201849052600160201b9092049091169063f2b9fdb89060440161468c565b6001600160a01b03821660009081526018602052604081205461484a90600190614e9d565b6000838152601a6020526040902054909150808203614899576001600160a01b03841660009081526019602090815260408083208584528252808320839055858352601a9091528120556124a7565b6001600160a01b0393909316600090815260196020908152604080832093835292815282822080548684528484208190558352601a9091528282209490945592839055908252812055565b6001600160e01b0319811681146117fd57600080fd5b60006020828403121561490c57600080fd5b81356111c7816148e4565b60005b8381101561493257818101518382015260200161491a565b50506000910152565b60008151808452614953816020860160208601614917565b601f01601f19169290920160200192915050565b6020815260006111c7602083018461493b565b60006020828403121561498c57600080fd5b5035919050565b80356001600160a01b03811681146149aa57600080fd5b919050565b600080604083850312156149c257600080fd5b6149cb83614993565b946020939093013593505050565b600080604083850312156149ec57600080fd5b50508035926020909101359150565b600060208284031215614a0d57600080fd5b6111c782614993565b600080600060608486031215614a2b57600080fd5b614a3484614993565b9250614a4260208501614993565b9150604084013590509250925092565b600060208284031215614a6457600080fd5b813563ffffffff811681146111c757600080fd5b634e487b7160e01b600052602160045260246000fd5b60038110614a9e57614a9e614a78565b9052565b602080825282518282018190526000919060409081850190868401855b82811015614b3057815180516001600160801b031685528681015187860152858101518686015260608082015163ffffffff1690860152608080820151614b0882880182614a8e565b505060a0818101519086015260c0908101519085015260e09093019290850190600101614abf565b5091979650505050505050565b60208101610f798284614a8e565b6020808252825182820181905260009190848201906040850190845b81811015614b8357835183529284019291840191600101614b67565b50909695505050505050565b600080600060608486031215614ba457600080fd5b505081359360208301359350604090920135919050565b80151581146117fd57600080fd5b60008060408385031215614bdc57600080fd5b614be583614993565b91506020830135614bf581614bbb565b809150509250929050565b600080600060608486031215614c1557600080fd5b8335925060208401359150614c2c60408501614993565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614c7457614c74614c35565b604052919050565b600080600060608486031215614c9157600080fd5b833567ffffffffffffffff80821115614ca957600080fd5b818601915086601f830112614cbd57600080fd5b8135602082821115614cd157614cd1614c35565b8160051b9250614ce2818401614c4b565b828152928401810192818101908a851115614cfc57600080fd5b948201945b84861015614d1a57853582529482019490820190614d01565b9a918901359950506040909701359695505050505050565b600067ffffffffffffffff821115614d4c57614d4c614c35565b50601f01601f191660200190565b60008060008060808587031215614d7057600080fd5b614d7985614993565b9350614d8760208601614993565b925060408501359150606085013567ffffffffffffffff811115614daa57600080fd5b8501601f81018713614dbb57600080fd5b8035614dce614dc982614d32565b614c4b565b818152886020838501011115614de357600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215614e1857600080fd5b614e2183614993565b9150614e2f60208401614993565b90509250929050565b6020808252600c908201526b37b7363c903430b7323632b960a11b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610f7957610f79614e74565b81810381811115610f7957610f79614e74565b634e487b7160e01b600052601260045260246000fd5b600082614ed557614ed5614eb0565b500490565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610f7957610f79614e74565b6020808252601290820152712737ba1037bbb732b91037b3103a37b5b2b760711b604082015260600190565b60208082526018908201527f6d757374206e6f74206c6f636b207768656e207374616b650000000000000000604082015260600190565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160801b0381811683821601908082111561336e5761336e614e74565b60008060408385031215614fe157600080fd5b505080516020909101519092909150565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001820161502857615028614e74565b5060010190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906118ce9083018461493b565b60006020828403121561507457600080fd5b81516111c7816148e4565b60006020828403121561509157600080fd5b815167ffffffffffffffff8111156150a857600080fd5b8201601f810184136150b957600080fd5b80516150c7614dc982614d32565b8181528560208385010111156150dc57600080fd5b611b23826020830160208601614917565b6000602082840312156150ff57600080fd5b81516111c781614bbb565b60006020828403121561511c57600080fd5b8151600881106111c757600080fd5b818103600083128015838313168383128216171561336e5761336e614e74565b600082600f0b82600f0b0280600f0b915080821461336e5761336e614e74565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610f7957610f79614e74565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610f7957610f79614e74565b63ffffffff8181168382160280821691908281146112ac576112ac614e74565b600063ffffffff808416806151fc576151fc614eb0565b92169190910492915050565b84815260208101849052608081016005841061522657615226614a78565b60408201939093526060015292915050565b600081600f0b83600f0b8061524f5761524f614eb0565b60016001607f1b031982146000198214161561526d5761526d614e74565b9005939250505056fea26469706673582212200c77112a5ea008b857c4fbf626792e934f523622ddfcfeb02623284a6c70749164736f6c63430008170033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef000000000000000000000000f08abd6513331def2d14881297bad5697180e2850000000000000000000000000599e29ed653c859ff2ca3571bb565d2d4f1fe1f0000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106104cd5760003560e01c8063869d2efc11610283578063bcebc7831161015c578063e7ac6b46116100ce578063ee99fe2811610092578063ee99fe2814610d1b578063f17156a714610d2e578063f2fde38b14610d41578063f6f518c614610d54578063f8a0576314610d6e578063fc0c546a14610d9157600080fd5b8063e7ac6b4614610c93578063e7e242d414610ca6578063e985e9c514610cb9578063ec36b40514610cf5578063ee552e3b14610d0857600080fd5b8063c87b56dd11610120578063c87b56dd14610be5578063d1febfb914610bf8578063d4e54c3b14610c36578063dacff02514610c49578063e0514aba14610c60578063e441135c14610c7357600080fd5b8063bcebc78314610b87578063c1e9cf9814610ba7578063c28b21f014610bba578063c2c4c5c114610bca578063c3b502e914610bd257600080fd5b80639cb7de4b116101f5578063a4d855df116101b9578063a4d855df14610aab578063aa33ac8114610abe578063aec2ccae14610ad1578063b45a3c0e14610af4578063b513ec9914610b61578063b88d4fde14610b7457600080fd5b80639cb7de4b14610a485780639d65e31114610a5b578063a003aac414610a6e578063a183af5214610a85578063a22cb46514610a9857600080fd5b8063900cf0cf11610247578063900cf0cf146109c15780639360b8dd146109ca57806395d89b41146109dd57806397518e0e14610a025780639782bebb14610a22578063981b24d014610a3557600080fd5b8063869d2efc146109645780638c2c9baf146109775780638da5cb5b1461098a5780638f7239e71461099b5780639007d70e146109ae57600080fd5b806342842e0e116103b55780636352211e116103275780637116c60c116102eb5780637116c60c146108d057806371197484146108e3578063715018a614610906578063719c98e21461090e578063722d7a07146109315780638462151c1461094457600080fd5b80636352211e1461083157806365fc38731461085a57806368bcc3fd1461086d5780636f5488371461089d57806370a08231146108bd57600080fd5b80635266d753116103795780635266d7531461079b57806354fd4d50146107be578063568e20f0146107e257806359c1a087146107f557806362431a5f1461080857806362f3765e1461082857600080fd5b806342842e0e14610729578063430c20811461073c578063461f711c1461074f57806346c96aac146107755780634bc2a6571461078857600080fd5b806323b872dd1161044e578063313ce56711610412578063313ce567146106a2578063329a8cfa146106bc578063379df6e1146106c45780633a589b97146106d75780633e00a8a414610703578063410509cf1461071657600080fd5b806323b872dd1461064357806323d304fc146106565780632e1a7d4d146106695780632f558a8f1461067c5780632f745c591461068f57600080fd5b8063136419931161049557806313641993146105b75780631376f3da146105ca57806318160ddd146106055780631a21c0bc1461060d5780631c984bc31461063057600080fd5b806301ffc9a7146104d2578063047fc9aa1461051457806306fdde031461052b578063081812fc14610561578063095ea7b3146105a2575b600080fd5b6104ff6104e03660046148fa565b6001600160e01b0319166000908152601c602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61051d60015481565b60405190815260200161050b565b6105546040518060400160405280600a8152602001691d99541bdcdd0813919560b21b81525081565b60405161050b9190614967565b61058a61056f36600461497a565b6000908152601760205260409020546001600160a01b031690565b6040516001600160a01b03909116815260200161050b565b6105b56105b03660046149af565b610db8565b005b6105b56105c536600461497a565b610ea0565b6105dd6105d83660046149d9565b610ef3565b60408051600f95860b81529390940b602084015292820152606081019190915260800161050b565b61051d610f3b565b6104ff61061b3660046149fb565b600d6020526000908152604090205460ff1681565b61051d61063e3660046149d9565b610f4b565b6105b5610651366004614a16565b610f7f565b6105b56106643660046149fb565b610f90565b6105b561067736600461497a565b610fba565b6105b561068a3660046149af565b610ff3565b61051d61069d3660046149af565b611069565b6106aa601281565b60405160ff909116815260200161050b565b6105b5611091565b6105b56106d23660046149fb565b61109c565b6011546106ee90600160c01b900463ffffffff1681565b60405163ffffffff909116815260200161050b565b6105b5610711366004614a52565b6110c6565b6105b561072436600461497a565b61114c565b6105b5610737366004614a16565b6111a0565b6104ff61074a3660046149af565b6111bb565b61076261075d36600461497a565b6111ce565b604051600f9190910b815260200161050b565b600e5461058a906001600160a01b031681565b6105b56107963660046149fb565b611212565b6104ff6107a93660046149fb565b60096020526000908152604090205460ff1681565b610554604051806040016040528060058152602001640312e302e360dc1b81525081565b61051d6107f03660046149af565b61123c565b6105b5610803366004614a52565b6112b4565b61081b6108163660046149af565b611339565b60405161050b9190614aa2565b6106ee61271081565b61058a61083f36600461497a565b6000908152601660205260409020546001600160a01b031690565b61051d6108683660046149d9565b611531565b61089061087b36600461497a565b600b6020526000908152604090205460ff1681565b60405161050b9190614b3d565b61051d6108ab36600461497a565b60036020526000908152604090205481565b61051d6108cb3660046149fb565b611575565b61051d6108de36600461497a565b611593565b6107626108f136600461497a565b600860205260009081526040902054600f0b81565b6105b56115f3565b6104ff61091c36600461497a565b600c6020526000908152604090205460ff1681565b6105b561093f3660046149fb565b611605565b6109576109523660046149fb565b61163a565b60405161050b9190614b4b565b6105b561097236600461497a565b6116e8565b61051d6109853660046149d9565b61177f565b6000546001600160a01b031661058a565b6105b56109a9366004614a52565b61178b565b6105b56109bc3660046149fb565b6117af565b61051d60045481565b61051d6109d8366004614b8f565b611800565b610554604051806040016040528060068152602001651d995413d4d560d21b81525081565b61051d610a103660046149fb565b60106020526000908152604090205481565b60135461058a906001600160a01b031681565b61051d610a4336600461497a565b6118d8565b6105b5610a56366004614bc9565b611a70565b61051d610a693660046149af565b611aa3565b6011546106ee90600160a01b900463ffffffff1681565b6105b5610a933660046149d9565b611b2c565b6105b5610aa6366004614bc9565b611dba565b6105b5610ab93660046149d9565b611e3e565b61051d610acc366004614c00565b61208b565b6104ff610adf3660046149fb565b600f6020526000908152604090205460ff1681565b610b36610b0236600461497a565b60026020819052600091825260409091208054600182015492820154600390920154600f9190910b92919063ffffffff1684565b60408051600f9590950b855260208501939093529183015263ffffffff16606082015260800161050b565b61051d610b6f366004614c7c565b612206565b6105b5610b82366004614d5a565b61237f565b61051d610b9536600461497a565b600a6020526000908152604090205481565b6105b5610bb5366004614a52565b6124ad565b6012546106ee9063ffffffff1681565b6105b56124db565b60145461058a906001600160a01b031681565b610554610bf336600461497a565b612541565b6105dd610c0636600461497a565b600560205260009081526040902080546001820154600290920154600f82810b93600160801b909304900b919084565b61051d610c44366004614c00565b6126e4565b6011546106ee90600160e01b900463ffffffff1681565b61051d610c6e3660046149d9565b612729565b61051d610c8136600461497a565b60076020526000908152604090205481565b6105b5610ca136600461497a565b612735565b61051d610cb436600461497a565b61277c565b6104ff610cc7366004614e05565b6001600160a01b039182166000908152601b6020908152604080832093909416825291909152205460ff1690565b61051d610d033660046149d9565b6127a5565b6105b5610d163660046149fb565b61291f565b6105b5610d293660046149d9565b612949565b60115461058a906001600160a01b031681565b6105b5610d4f3660046149fb565b612b46565b60125461058a90600160201b90046001600160a01b031681565b61051d610d7c36600461497a565b60009081526002602052604090206001015490565b61058a7f000000000000000000000000f08abd6513331def2d14881297bad5697180e28581565b6000818152601660205260409020546001600160a01b031680610dda57600080fd5b806001600160a01b0316836001600160a01b031603610df857600080fd5b6000828152601660209081526040808320546001600160a01b038581168552601b845282852033808752945291909320549216149060ff168180610e395750805b610e4257600080fd5b60008481526017602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050505050565b336000908152600d602052604090205460ff16610ed85760405162461bcd60e51b8152600401610ecf90614e38565b60405180910390fd5b6000908152600c60205260409020805460ff19166001179055565b6006602052816000526040600020816402540be4008110610f1357600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6000610f4642611593565b905090565b6000828152600660205260408120826402540be4008110610f6e57610f6e614e5e565b600302016001015490505b92915050565b610f8b83838333612b81565b505050565b610f98612cff565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b601d5460ff16600114610fcc57600080fd5b601d805460ff19166002179055610fe38133612d2c565b50601d805460ff19166001179055565b600e546001600160a01b031633146110385760405162461bcd60e51b815260206004820152600860248201526737b7363c9023b7bb60c11b6044820152606401610ecf565b6001600160a01b039091166000908152600f60209081526040808320805460ff191660011790556010909152902055565b6001600160a01b03919091166000908152601960209081526040808320938352929052205490565b61109a33613155565b565b6110a4612cff565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b6110ce612cff565b61271063ffffffff821610156111265760405162461bcd60e51b815260206004820152601f60248201527f626f6f7374546f6b656e206d757374203e3d20424153455f50455243454e54006044820152606401610ecf565b6011805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b601d5460ff1660011461115e57600080fd5b601d805460ff191660021790556000818152601660205260408120546001600160a01b0316905061118f8282612d2c565b5050601d805460ff19166001179055565b610f8b8383836040518060200160405280600081525061237f565b60006111c78383613233565b9392505050565b60008181526007602090815260408083205460069092528220816402540be40081106111fc576111fc614e5e565b6003020154600160801b9004600f0b9392505050565b61121a612cff565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000806112488461163a565b9050805160000361125d576000915050610f79565b82600003611269574292505b60005b81518110156112ac5761129882828151811061128a5761128a614e5e565b602002602001015185612729565b6112a29084614e8a565b925060010161126c565b505092915050565b6112bc612cff565b61271063ffffffff821610156113145760405162461bcd60e51b815260206004820181905260248201527f5f626f6f73744c504e6674206d757374203e3d20424153455f50455243454e546044820152606401610ecf565b6011805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b6060600061135c846001600160a01b031660009081526018602052604090205490565b905060008167ffffffffffffffff81111561137957611379614c35565b6040519080825280602002602001820160405280156113ea57816020015b6113d76040805160e08101825260008082526020820181905291810182905260608101829052906080820190815260200160008152602001600081525090565b8152602001906001900390816113975790505b50604080516080810182526000808252602082018190529181018290526060810182905291925090600086600003611420574296505b60005b85811015611524576114358982611069565b60008181526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff166060820152909450925061148b8489613299565b6040805160e08101825285516001600160801b0316815260208087015181830152868301518284015260608088015163ffffffff16908301526000888152600b909152919091205491935090608082019060ff1660028111156114f0576114f0614a78565b81526020018381526020018581525085828151811061151157611511614e5e565b6020908102919091010152600101611423565b5092979650505050505050565b601d5460009060ff1660011461154657600080fd5b601d805460ff191660021790556115608383336001613375565b9050601d805460ff1916600117905592915050565b6001600160a01b038116600090815260186020526040812054610f79565b600454600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001810154918301919091526002015460608201529091906115eb81856135e0565b949350505050565b6115fb612cff565b61109a60006136d9565b61160d612cff565b601280546001600160a01b03909216600160201b02640100000000600160c01b0319909216919091179055565b6060600061165d836001600160a01b031660009081526018602052604090205490565b905060008167ffffffffffffffff81111561167a5761167a614c35565b6040519080825280602002602001820160405280156116a3578160200160208202803683370190505b50905060005b828110156116e0576116bb8582611069565b8282815181106116cd576116cd614e5e565b60209081029190910101526001016116a9565b509392505050565b336000908152600d602052604090205460ff166117175760405162461bcd60e51b8152600401610ecf90614e38565b601254604051635d7d9d2b60e11b815260048101839052600160201b9091046001600160a01b03169063bafb3a56906024015b600060405180830381600087803b15801561176457600080fd5b505af1158015611778573d6000803e3d6000fd5b5050505050565b60006111c78383613729565b611793612cff565b6012805463ffffffff191663ffffffff92909216919091179055565b600e546001600160a01b031633146117f45760405162461bcd60e51b815260206004820152600860248201526737b7363c9023b7bb60c11b6044820152606401610ecf565b6117fd81613155565b50565b600083815260026020818152604080842081516080810183528154600f0b8152600182015493810184905293810154918401919091526003015463ffffffff16606083015283111561188357601254602082015163ffffffff909116906118679085614e9d565b10156118795780602001519250611883565b60009150506111c7565b8284118061189357508051600f0b155b156118a25760009150506111c7565b600060026118b08786613299565b6118ba8888613299565b6118c49190614e8a565b6118ce9190614ec6565b9695505050505050565b6000438211156118ea576118ea614eda565b60045460006118f98483613a02565b600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606082015291925083831015611a0857600060058161195c866001614e8a565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905285015191925014611a0257826060015181606001516119c89190614e9d565b836040015182604001516119dc9190614e9d565b60608501516119eb908a614e9d565b6119f59190614ef0565b6119ff9190614ec6565b91505b50611a57565b43826060015114611a57576060820151611a229043614e9d565b6040830151611a319042614e9d565b6060840151611a409089614e9d565b611a4a9190614ef0565b611a549190614ec6565b90505b6118ce82828460400151611a6b9190614e8a565b6135e0565b611a78612cff565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b6000806000611ab18561163a565b90508051600003611ac757600092505050610f79565b83600003611ad3574293505b60005b8151811015611b1657611b02828281518110611af457611af4614e5e565b602002602001015186612729565b611b0c9084614e8a565b9250600101611ad6565b508051611b239083614ec6565b95945050505050565b601d5460ff16600114611b3e57600080fd5b601d805460ff19166002179055611b553383613233565b611b715760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615611ba05760405162461bcd60e51b8152600401610ecf90614f33565b6000828152600a602052604090205415611bfc5760405162461bcd60e51b815260206004820152601a60248201527f4d757374206e6f7420697320756e6953776170206e6674206c700000000000006044820152606401610ecf565b60008281526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff16606082015281611c815760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610ecf565b60008160000151600f0b13611cd15760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610ecf565b42816020015111611cf45760405162461bcd60e51b8152600401610ecf90614f6a565b601260049054906101000a90046001600160a01b03166001600160a01b03166304650cbd3385858560000151611d2a9190614fae565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526001600160801b03166044820152606401600060405180830381600087803b158015611d8157600080fd5b505af1158015611d95573d6000803e3d6000fd5b50505050611da883836000846003613a80565b5050601d805460ff1916600117905550565b336001600160a01b03831603611dd257611dd2614eda565b336000818152601b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b601d5460ff16600114611e5057600080fd5b601d805460ff19166002179055611e673383613233565b611e835760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615611eb25760405162461bcd60e51b8152600401610ecf90614f33565b600082815260026020818152604080842081516080810183528154600f0b8152600182015493810193909352928301549082015260039091015463ffffffff1660608201529062093a8080611f078542614e8a565b611f119190614ec6565b611f1b9190614ef0565b905042826020015111611f5f5760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b6044820152606401610ecf565b60008260000151600f0b13611faa5760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b6044820152606401610ecf565b81602001518111611ffd5760405162461bcd60e51b815260206004820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152606401610ecf565b61200b630784ce0042614e8a565b81111561205a5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610ecf565b42604083015261206933613da4565b61207884600083856004613a80565b5050601d805460ff191660011790555050565b601d5460009060ff166001146120a057600080fd5b601d805460ff191660021790556013546040516313421d2b60e31b8152600481018690526000916001600160a01b031690639a10e958906024016040805180830381865afa1580156120f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211a9190614fce565b509050600081116121685760405162461bcd60e51b8152602060048201526018602482015277139bc81c1bdcdd08185b5bdd5b9d081a5b8813140813919560421b6044820152606401610ecf565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd9061219c90339030908a90600401614ff2565b600060405180830381600087803b1580156121b657600080fd5b505af11580156121ca573d6000803e3d6000fd5b5050505060006121dd8286866002613375565b6000818152600a6020526040902087905592505050601d805460ff191660011790559392505050565b60008080805b865181101561235d5760006002600089848151811061222d5761222d614e5e565b6020908102919091018101518252818101929092526040908101600090812082516080810184528154600f0b8082526001830154958201959095526002820154938101939093526003015463ffffffff166060830152909250036122915750612355565b8261229b81615016565b93505080602001518611156122dd57601254602082015163ffffffff909116906122c59088614e9d565b10156122d757806020015195506122dd565b50612355565b60008688101561234657600261230c8a85815181106122fe576122fe614e5e565b602002602001015189613299565b61232f8b868151811061232157612321614e5e565b60200260200101518b613299565b6123399190614e8a565b6123439190614ec6565b90505b6123508186614e8a565b945050505b60010161220c565b5080156123735761236e8183614ec6565b6118ce565b60009695505050505050565b61238b84848433612b81565b823b156124a757604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906123c490339088908790879060040161502f565b6020604051808303816000875af19250505080156123ff575060408051601f3d908101601f191682019092526123fc91810190615062565b60015b611778573d80801561242d576040519150601f19603f3d011682016040523d82523d6000602084013e612432565b606091505b50805160000361249f5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610ecf565b805181602001fd5b50505050565b6124b5612cff565b6011805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61109a600060405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff1681525060405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff16815250613de1565b6000818152601660205260409020546060906001600160a01b03166125a85760405162461bcd60e51b815260206004820152601b60248201527f517565727920666f72206e6f6e6578697374656e7420746f6b656e00000000006044820152606401610ecf565b600082815260026020818152604080842081516080810183528154600f0b815260018083015482860152828601548285015260039092015463ffffffff166060820152601454888752600b909452919094205490936001600160a01b03909216926353dd3389928792909160ff9091169081111561262857612628614a78565b14612634576002612637565b60015b604085015160208601514260608801516126518b42613299565b6040516001600160e01b031960e08a901b168152600481019790975260ff909516602487015260448601939093526064850191909152608484015263ffffffff1660a483015260c482015260e401600060405180830381865afa1580156126bc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111c7919081019061507f565b601d5460009060ff166001146126f957600080fd5b601d805460ff191660021790556127138484846001613375565b9050601d805460ff191660011790559392505050565b60006111c78383613299565b336000908152600d602052604090205460ff166127645760405162461bcd60e51b8152600401610ecf90614e38565b6000908152600c60205260409020805460ff19169055565b6000436000838152600360205260409020540361279b57506000919050565b610f798242613299565b601d5460009060ff166001146127ba57600080fd5b601d805460ff191660021790556013546040516313421d2b60e31b8152600481018590526000916001600160a01b031690639a10e958906024016040805180830381865afa158015612810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128349190614fce565b509050600081116128825760405162461bcd60e51b8152602060048201526018602482015277139bc81c1bdcdd08185b5bdd5b9d081a5b8813140813919560421b6044820152606401610ecf565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906128b690339030908990600401614ff2565b600060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b5050505060006128f78285336002613375565b6000818152600a6020526040902086905592505050601d805460ff1916600117905592915050565b612927612cff565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b601d5460ff1660011461295b57600080fd5b601d805460ff1916600290811790915560008381526020828152604080832081516080810183528154600f0b815260018201548185015294810154858301526003015463ffffffff166060850152858352600a90915290205415612a015760405162461bcd60e51b815260206004820152601a60248201527f4d757374206e6f7420697320756e6953776170206e6674206c700000000000006044820152606401610ecf565b60008211612a0e57600080fd5b60008160000151600f0b13612a5e5760405162461bcd60e51b8152602060048201526016602482015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b6044820152606401610ecf565b42816020015111612a815760405162461bcd60e51b8152600401610ecf90614f6a565b6012546001600160a01b03600160201b909104166304650cbd612ab9856000908152601660205260409020546001600160a01b031690565b83518690612ac8908790614fae565b6040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526001600160801b03166044820152606401600060405180830381600087803b158015612b1f57600080fd5b505af1158015612b33573d6000803e3d6000fd5b50505050611da883836000846000613a80565b612b4e612cff565b6001600160a01b038116612b7857604051631e4fbdf760e01b815260006004820152602401610ecf565b6117fd816136d9565b612b8a84613155565b6001600160a01b0384166000908152600f602052604090205460ff1615612be55760405162461bcd60e51b815260206004820152600f60248201526e746f6b656e20696e20766f74696e6760881b6044820152606401610ecf565b6015546000908152600c602052604090205460ff1615612c405760405162461bcd60e51b815260206004820152601660248201527536bab9ba103737ba103637b1b5903a3930b739b332b960511b6044820152606401610ecf565b612c4a8183613233565b612c885760405162461bcd60e51b815260206004820152600f60248201526e2737ba1037bbb732b9103a37b5b2b760891b6044820152606401610ecf565b612c93848484614419565b612c9d84836144d1565b612ca78483614538565b612cb183836145b9565b6000828152600360205260408082204390555183916001600160a01b0386811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000546001600160a01b0316331461109a5760405163118cdaa760e01b8152336004820152602401610ecf565b612d368183613233565b612d525760405162461bcd60e51b8152600401610ecf90614f07565b6000828152600c602052604090205460ff1615612d815760405162461bcd60e51b8152600401610ecf90614f33565b6000828152601660205260409020546001600160a01b0316612da281613155565b6001600160a01b0381166000908152600f602052604090205460ff1615612dfd5760405162461bcd60e51b815260206004820152600f60248201526e746f6b656e20696e20766f74696e6760881b6044820152606401610ecf565b612e07828461464f565b60008381526002602081815260409283902083516080810185528154600f0b81526001820154928101839052928101549383019390935260039092015463ffffffff16606082015290421015612e985760405162461bcd60e51b8152602060048201526016602482015275546865206c6f636b206469646e27742065787069726560501b6044820152606401610ecf565b80516040805160808101825260008082526020808301828152838501838152606085018481528b855260029384905295909320935184546001600160801b0319166001600160801b039091161784555160018085019190915591519083015591516003909101805463ffffffff191663ffffffff90921691909117905554600f9190910b90612f278282614e9d565b600181905550612f65868460405180608001604052806000600f0b81526020016000815260200160008152602001600063ffffffff16815250613de1565b6000868152600a6020526040812054908190036130205760405163a9059cbb60e01b81526001600160a01b038781166004830152602482018590527f000000000000000000000000f08abd6513331def2d14881297bad5697180e285169063a9059cbb906044016020604051808303816000875af1158015612feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300f91906150ed565b61301b5761301b614eda565b613096565b6011546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906130549030908a908690600401614ff2565b600060405180830381600087803b15801561306e57600080fd5b505af1158015613082573d6000803e3d6000fd5b5050506000888152600a6020526040812055505b6000878152600b60205260409020805460ff191690556130b5876146c2565b6001600160a01b0386167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948885426040805193845260208401929092529082015260600160405180910390a27f21e69d6eb75b6c23bbc769d20f147b2d4bd10ffdaef330c7bf634c2686302fa78261312d8582614e9d565b426040805193845260208401929092529082015260600160405180910390a150505050505050565b6001600160a01b0381166000908152601060205260408120549081900361317a575050565b600e54604051631f27a4f360e11b8152600481018390526000916001600160a01b031690633e4f49e690602401602060405180830381865afa1580156131c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e8919061510a565b905060018160078111156131fe576131fe614a78565b14610f8b57610f8b836001600160a01b03166000908152600f60209081526040808320805460ff191690556010909152812055565b60008181526016602090815260408083205460178352818420546001600160a01b03918216808652601b855283862088841680885295529285205492938085149392909116149060ff1682806132865750815b8061328e5750805b979650505050505050565b6000828152600760205260408120548082036132b9576000915050610f79565b6000848152600660205260408120826402540be40081106132dc576132dc614e5e565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b602083015260018101549282018390526002015460608201529150613328908561512b565b8160200151613337919061514b565b8151829061334690839061516b565b600f90810b90915282516000910b1215905061336157600081525b51600f0b9150610f799050565b5092915050565b60008062093a80806133878742614e8a565b6133919190614ec6565b61339b9190614ef0565b9050600086116133dd5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b6044820152606401610ecf565b42811161343b5760405162461bcd60e51b815260206004820152602660248201527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e207468652060448201526566757475726560d01b6064820152608401610ecf565b613449630784ce0042614e8a565b8111156134985760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d617800006044820152606401610ecf565b6276a7008510156134eb5760405162461bcd60e51b815260206004820152601d60248201527f566f74696e67206c6f636b206d7573742033206d6f6e746873206d696e0000006044820152606401610ecf565b6015600081546134fa90615016565b9091555060155461350b8582614781565b50600284600481111561352057613520614a78565b03613543576000818152600b60205260409020805460ff19166002179055613576565b600184600481111561355757613557614a78565b03613576576000818152600b60205260409020805460ff191660011790555b61357f85613da4565b60008181526002602081815260409283902083516080810185528154600f0b815260018201549281019290925291820154928101929092526003015463ffffffff1660608201526135d69082908990859088613a80565b6118ce85826147e4565b600080839050600062093a808083604001516135fc9190614ec6565b6136069190614ef0565b905060005b60ff8110156136b15761362162093a8083614e8a565b915060008583111561363557859250613649565b50600082815260086020526040902054600f0b5b60408401516136589084614e9d565b8460200151613667919061514b565b8451859061367690839061516b565b600f0b90525085830361368957506136b1565b808460200181815161369b9190615198565b600f0b905250506040830182905260010161360b565b5060008260000151600f0b12156136c757600082525b50516001600160801b03169392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60004382111561373b5761373b614eda565b600083815260076020526040812054815b60808110156137d457818310156137d4576000600261376b8486614e8a565b613776906001614e8a565b6137809190614ec6565b60008881526006602052604090209091508690826402540be40081106137a8576137a8614e5e565b6003020160020154116137bd578093506137cb565b6137c8600182614e9d565b92505b5060010161374c565b506000858152600660205260408120836402540be40081106137f8576137f8614e5e565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201929092526002909101546060820152600454909150600061384d8783613a02565b600081815260056020908152604080832081516080810183528154600f81810b8352600160801b909104900b93810193909352600181015491830191909152600201546060820152919250808484101561392c5760006005816138b1876001614e8a565b8152602080820192909252604090810160002081516080810183528154600f81810b8352600160801b909104900b9381019390935260018101549183019190915260020154606080830182905286015191925061390e9190614e9d565b9250836040015181604001516139249190614e9d565b915050613956565b606083015161393b9043614e9d565b915082604001516139494290565b6139539190614e9d565b90505b60408301518215613993578284606001518c6139729190614e9d565b61397c9084614ef0565b6139869190614ec6565b6139909082614e8a565b90505b60408701516139a29082614e9d565b87602001516139b1919061514b565b875188906139c090839061516b565b600f90810b90915288516000910b1290506139f057505093516001600160801b03169650610f7995505050505050565b60009950505050505050505050610f79565b60008082815b6080811015613a765781831015613a765760006002613a278486614e8a565b613a32906001614e8a565b613a3c9190614ec6565b6000818152600560205260409020600201549091508710613a5f57809350613a6d565b613a6a600182614e9d565b92505b50600101613a08565b5090949350505050565b6001548290613a8f8682614e8a565b600155604080516080810182526000808252602080830182815293830182905260608084019283528651918701519087015163ffffffff169092529252600f9190910b8152825187908490613ae5908390615198565b600f0b9052508515613af957602083018690525b8260400151600003613b0c574260408401525b826060015163ffffffff16600003613bd1576127106002856004811115613b3557613b35614a78565b03613b725760115461271090613b619063ffffffff600160a01b8204811691600160e01b9004166151c5565b613b6b91906151e5565b9050613bbf565b6001856004811115613b8657613b86614a78565b03613bbf5760115461271090613bb29063ffffffff600160a01b8204811691600160c01b9004166151c5565b613bbc91906151e5565b90505b63ffffffff1660608083018290528401525b600088815260026020818152604092839020865181546001600160801b0319166001600160801b03909116178155908601516001820155918501519082015560608401516003909101805463ffffffff191663ffffffff909216919091179055613c3c888285613de1565b338715801590613c5e57506002856004811115613c5b57613c5b614a78565b14155b15613d02576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000f08abd6513331def2d14881297bad5697180e28516906323b872dd90613cb390849030908d90600401614ff2565b6020604051808303816000875af1158015613cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf691906150ed565b613d0257613d02614eda565b60208401516001600160a01b0382167fff04ccafc360e16b67d682d17bd9503c4c6b9a131f6be6325762dc9ffc7de6248b8b8942604051613d469493929190615208565b60405180910390a37f21e69d6eb75b6c23bbc769d20f147b2d4bd10ffdaef330c7bf634c2686302fa783613d7a8a82614e8a565b426040805193845260208401929092529082015260600160405180910390a1505050505050505050565b6012546040516001623d2ea360e11b031981526001600160a01b038381166004830152600160201b9092049091169063ff85a2ba9060240161174a565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260045460009081908715613f8257428760200151118015613e51575060008760000151600f0b135b15613eb157613e66612710630784ce0061514b565b87516060890151613e7a919060030b61514b565b613e849190615238565b600f0b6020860152428760200151613e9c9190614e9d565b8560200151613eab919061514b565b600f0b85525b428660200151118015613ecb575060008660000151600f0b135b15613f2b57613ee0612710630784ce0061514b565b86516060880151613ef4919060030b61514b565b613efe9190615238565b600f0b6020850152428660200151613f169190614e9d565b8460200151613f25919061514b565b600f0b84525b602080880151600090815260088252604090205490870151600f9190910b935015613f82578660200151866020015103613f6757829150613f82565b602080870151600090815260089091526040902054600f0b91505b604080516080810182526000808252602082015242918101919091524360608201528115613ff7575060008181526005602090815260409182902082516080810184528154600f81810b8352600160801b909104900b9281019290925260018101549282019290925260029091015460608201525b6040810151816000824211156140445760408401516140169042614e9d565b60608501516140259043614e9d565b61403790670de0b6b3a7640000614ef0565b6140419190614ec6565b90505b600062093a806140548186614ec6565b61405e9190614ef0565b905060005b60ff8110156141d05761407962093a8083614e8a565b915060004283111561408d574292506140a1565b50600082815260086020526040902054600f0b5b6140ab8684614e9d565b87602001516140ba919061514b565b875188906140c990839061516b565b600f0b9052506020870180518291906140e3908390615198565b600f90810b90915288516000910b121590506140fe57600087525b60008760200151600f0b121561411657600060208801525b60408088018490528501519295508592670de0b6b3a76400009061413a9085614e9d565b6141449086614ef0565b61414e9190614ec6565b856060015161415d9190614e8a565b606088015261416d600189614e8a565b975042830361418257436060880152506141d0565b6000888152600560209081526040918290208951918a01516001600160801b03908116600160801b029216919091178155908801516001820155606088015160029091015550600101614063565b505060048590558b1561425b57886020015188602001516141f1919061516b565b846020018181516142029190615198565b600f0b90525088518851614216919061516b565b84518590614225908390615198565b600f90810b90915260208601516000910b1215905061424657600060208501525b60008460000151600f0b121561425b57600084525b6000858152600560209081526040918290208651918701516001600160801b03908116600160801b02921691909117815590850151600182015560608501516002909101558b1561440b57428b6020015111156143125760208901516142c19088615198565b96508a602001518a60200151036142e45760208801516142e1908861516b565b96505b60208b810151600090815260089091526040902080546001600160801b0319166001600160801b0389161790555b428a60200151111561436d578a602001518a60200151111561436d57602088015161433d908761516b565b60208b810151600090815260089091526040902080546001600160801b0319166001600160801b03831617905595505b60008c815260076020526040812054614387906001614e8a565b60008e815260076020526040902081905590504260408a01524360608a015260008d81526006602052604090208990826402540be40081106143cb576143cb614e5e565b825160208401516001600160801b03908116600160801b029116176003919091029190910190815560408201516001820155606090910151600290910155505b505050505050505050505050565b6001600160a01b03821660009081526009602052604090205460ff1615801561445b57506001600160a01b03831660009081526009602052604090205460ff16155b15610f8b57601254604051633b6a328960e11b8152600160201b9091046001600160a01b0316906376d465129061449a90869086908690600401614ff2565b600060405180830381600087803b1580156144b457600080fd5b505af11580156144c8573d6000803e3d6000fd5b50505050505050565b6000818152601660205260409020546001600160a01b038381169116146144fa576144fa614eda565b6000818152601760205260409020546001600160a01b03161561453457600081815260176020526040902080546001600160a01b03191690555b5050565b6000818152601660205260409020546001600160a01b0383811691161461456157614561614eda565b600081815260166020526040902080546001600160a01b03191690556145878282614825565b6001600160a01b03821660009081526018602052604081208054600192906145b0908490614e9d565b90915550505050565b6000818152601660205260409020546001600160a01b0316156145de576145de614eda565b600081815260166020908152604080832080546001600160a01b0319166001600160a01b03871690811790915580845260188084528285208054601986528487208188528652848720889055878752601a8652938620939093559084529091528054600192906145b0908490614e8a565b601254604051633c3ad31960e01b81526001600160a01b03848116600483015260248201849052600160201b90920490911690633c3ad319906044015b600060405180830381600087803b1580156146a657600080fd5b505af11580156146ba573d6000803e3d6000fd5b505050505050565b6146cc3382613233565b6147185760405162461bcd60e51b815260206004820181905260248201527f63616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610ecf565b6000818152601660205260408120546001600160a01b03169061473b9083610db8565b6147453383614538565b60405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60006001600160a01b03831661479957614799614eda565b6147a383836145b9565b60405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a450600192915050565b601254604051631e573fb760e31b81526001600160a01b03848116600483015260248201849052600160201b9092049091169063f2b9fdb89060440161468c565b6001600160a01b03821660009081526018602052604081205461484a90600190614e9d565b6000838152601a6020526040902054909150808203614899576001600160a01b03841660009081526019602090815260408083208584528252808320839055858352601a9091528120556124a7565b6001600160a01b0393909316600090815260196020908152604080832093835292815282822080548684528484208190558352601a9091528282209490945592839055908252812055565b6001600160e01b0319811681146117fd57600080fd5b60006020828403121561490c57600080fd5b81356111c7816148e4565b60005b8381101561493257818101518382015260200161491a565b50506000910152565b60008151808452614953816020860160208601614917565b601f01601f19169290920160200192915050565b6020815260006111c7602083018461493b565b60006020828403121561498c57600080fd5b5035919050565b80356001600160a01b03811681146149aa57600080fd5b919050565b600080604083850312156149c257600080fd5b6149cb83614993565b946020939093013593505050565b600080604083850312156149ec57600080fd5b50508035926020909101359150565b600060208284031215614a0d57600080fd5b6111c782614993565b600080600060608486031215614a2b57600080fd5b614a3484614993565b9250614a4260208501614993565b9150604084013590509250925092565b600060208284031215614a6457600080fd5b813563ffffffff811681146111c757600080fd5b634e487b7160e01b600052602160045260246000fd5b60038110614a9e57614a9e614a78565b9052565b602080825282518282018190526000919060409081850190868401855b82811015614b3057815180516001600160801b031685528681015187860152858101518686015260608082015163ffffffff1690860152608080820151614b0882880182614a8e565b505060a0818101519086015260c0908101519085015260e09093019290850190600101614abf565b5091979650505050505050565b60208101610f798284614a8e565b6020808252825182820181905260009190848201906040850190845b81811015614b8357835183529284019291840191600101614b67565b50909695505050505050565b600080600060608486031215614ba457600080fd5b505081359360208301359350604090920135919050565b80151581146117fd57600080fd5b60008060408385031215614bdc57600080fd5b614be583614993565b91506020830135614bf581614bbb565b809150509250929050565b600080600060608486031215614c1557600080fd5b8335925060208401359150614c2c60408501614993565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614c7457614c74614c35565b604052919050565b600080600060608486031215614c9157600080fd5b833567ffffffffffffffff80821115614ca957600080fd5b818601915086601f830112614cbd57600080fd5b8135602082821115614cd157614cd1614c35565b8160051b9250614ce2818401614c4b565b828152928401810192818101908a851115614cfc57600080fd5b948201945b84861015614d1a57853582529482019490820190614d01565b9a918901359950506040909701359695505050505050565b600067ffffffffffffffff821115614d4c57614d4c614c35565b50601f01601f191660200190565b60008060008060808587031215614d7057600080fd5b614d7985614993565b9350614d8760208601614993565b925060408501359150606085013567ffffffffffffffff811115614daa57600080fd5b8501601f81018713614dbb57600080fd5b8035614dce614dc982614d32565b614c4b565b818152886020838501011115614de357600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215614e1857600080fd5b614e2183614993565b9150614e2f60208401614993565b90509250929050565b6020808252600c908201526b37b7363c903430b7323632b960a11b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610f7957610f79614e74565b81810381811115610f7957610f79614e74565b634e487b7160e01b600052601260045260246000fd5b600082614ed557614ed5614eb0565b500490565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610f7957610f79614e74565b6020808252601290820152712737ba1037bbb732b91037b3103a37b5b2b760711b604082015260600190565b60208082526018908201527f6d757374206e6f74206c6f636b207768656e207374616b650000000000000000604082015260600190565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6001600160801b0381811683821601908082111561336e5761336e614e74565b60008060408385031215614fe157600080fd5b505080516020909101519092909150565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001820161502857615028614e74565b5060010190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906118ce9083018461493b565b60006020828403121561507457600080fd5b81516111c7816148e4565b60006020828403121561509157600080fd5b815167ffffffffffffffff8111156150a857600080fd5b8201601f810184136150b957600080fd5b80516150c7614dc982614d32565b8181528560208385010111156150dc57600080fd5b611b23826020830160208601614917565b6000602082840312156150ff57600080fd5b81516111c781614bbb565b60006020828403121561511c57600080fd5b8151600881106111c757600080fd5b818103600083128015838313168383128216171561336e5761336e614e74565b600082600f0b82600f0b0280600f0b915080821461336e5761336e614e74565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610f7957610f79614e74565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610f7957610f79614e74565b63ffffffff8181168382160280821691908281146112ac576112ac614e74565b600063ffffffff808416806151fc576151fc614eb0565b92169190910492915050565b84815260208101849052608081016005841061522657615226614a78565b60408201939093526060015292915050565b600081600f0b83600f0b8061524f5761524f614eb0565b60016001607f1b031982146000198214161561526d5761526d614e74565b9005939250505056fea26469706673582212200c77112a5ea008b857c4fbf626792e934f523622ddfcfeb02623284a6c70749164736f6c63430008170033

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

000000000000000000000000f08abd6513331def2d14881297bad5697180e2850000000000000000000000000599e29ed653c859ff2ca3571bb565d2d4f1fe1f0000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : token_addr (address): 0xf08abd6513331dEF2d14881297baD5697180e285
Arg [1] : _lpNft (address): 0x0599E29ed653C859fF2ca3571BB565d2D4f1fe1F
Arg [2] : _vePostNFTSVG (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000f08abd6513331def2d14881297bad5697180e285
Arg [1] : 0000000000000000000000000599e29ed653c859ff2ca3571bb565d2d4f1fe1f
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000


[ Download: CSV Export  ]
[ Download: CSV Export  ]

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