ETH Price: $3,450.61 (-1.07%)
Gas: 8 Gwei

Token

Keep3r Options (oKP3R)
 

Overview

Max Total Supply

75 oKP3R

Holders

69

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 oKP3R
0xe91e1ec05adb7f06934db658bea31a753fa460ea
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Keep3rOptions

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU LGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-09-12
*/

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

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}


interface IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    function balanceOf(address owner) external view returns (uint256 balance);
    function ownerOf(uint256 tokenId) external view returns (address owner);
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address operator);
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

library Strings {
    function toString(uint256 value) internal pure returns (string memory) {
        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);
    }
}

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

abstract contract ERC165 is IERC165 {
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

contract ERC721 is ERC165, IERC721 {
    using Strings for uint256;

    mapping(uint256 => address) private _owners;
    mapping(address => uint256) private _balances;
    mapping(uint256 => address) private _tokenApprovals;
    mapping(address => mapping(address => bool)) private _operatorApprovals;

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

    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

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

        _approve(to, tokenId);
    }

    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != msg.sender, "ERC721: approve to caller");

        _operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function _isContract(address account) internal view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

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

        _transfer(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

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

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

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

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

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

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

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

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

        _balances[to] += 1;
        _owners[tokenId] = to;

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

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

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

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

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

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

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (_isContract(to)) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

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







/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

library FullMath {
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(a, b, not(0))
            prod0 := mul(a, b)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        if (prod1 == 0) {
            require(denominator > 0);
            assembly {
                result := div(prod0, denominator)
            }
            return result;
        }

        require(denominator > prod1);

        uint256 remainder;
        assembly {
            remainder := mulmod(a, b, denominator)
        }
        assembly {
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }
        int256 _denominator = int256(denominator);
        uint256 twos = uint256(-_denominator & _denominator);
        assembly {
            denominator := div(denominator, twos)
        }

        assembly {
            prod0 := div(prod0, twos)
        }

        assembly {
            twos := add(div(sub(0, twos), twos), 1)
        }
        prod0 |= prod1 * twos;

        uint256 inv = (3 * denominator) ^ 2;

        inv *= 2 - denominator * inv; // inverse mod 2**8
        inv *= 2 - denominator * inv; // inverse mod 2**16
        inv *= 2 - denominator * inv; // inverse mod 2**32
        inv *= 2 - denominator * inv; // inverse mod 2**64
        inv *= 2 - denominator * inv; // inverse mod 2**128
        inv *= 2 - denominator * inv; // inverse mod 2**256

        result = prod0 * inv;
        return result;
    }
}

library TickMath {
    int24 internal constant MIN_TICK = -887272;
    int24 internal constant MAX_TICK = -MIN_TICK;

    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
        require(absTick <= uint256(int256(MAX_TICK)), 'T');

        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

        if (tick > 0) ratio = type(uint256).max / ratio;

        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
    }
}

interface IUniswapV3Pool {
        function observe(uint32[] calldata secondsAgos)
        external
        view
        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);
}

/// @title Oracle library
/// @notice Provides functions to integrate with V3 pool oracle
library OracleLibrary {
    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle
    /// @param pool Address of Uniswap V3 pool that we want to observe
    /// @param period Number of seconds in the past to start calculating time-weighted average
    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp
    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {
        require(period != 0, 'BP');

        uint32[] memory secondAgos = new uint32[](2);
        secondAgos[0] = period;
        secondAgos[1] = 0;

        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);
        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];

        timeWeightedAverageTick = int24(tickCumulativesDelta / int(uint(period)));

        // Always round to negative infinity
        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int(uint(period)) != 0)) timeWeightedAverageTick--;
    }

    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange
    /// @param tick Tick value used to calculate the quote
    /// @param baseAmount Amount of token to be converted
    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination
    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination
    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken
    function getQuoteAtTick(
        int24 tick,
        uint128 baseAmount,
        address baseToken,
        address quoteToken
    ) internal pure returns (uint256 quoteAmount) {
        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);

        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself
        if (sqrtRatioX96 <= type(uint128).max) {
            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;
            quoteAmount = baseToken < quoteToken
                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)
                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);
        } else {
            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);
            quoteAmount = baseToken < quoteToken
                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)
                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);
        }
    }
}

library PoolAddress {
    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;

    struct PoolKey {
        address token0;
        address token1;
        uint24 fee;
    }function getPoolKey(
        address tokenA,
        address tokenB,
        uint24 fee
    ) internal pure returns (PoolKey memory) {
        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
    }

    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
        require(key.token0 < key.token1);
        pool = address(
            uint160(uint256(
                keccak256(
                    abi.encodePacked(
                        hex'ff',
                        factory,
                        keccak256(abi.encode(key.token0, key.token1, key.fee)),
                        POOL_INIT_CODE_HASH
                    )
                )
            )
        ));
    }
}

library SafeUint128 {
    function toUint128(uint256 y) internal pure returns (uint128 z) {
        require((z = uint128(y)) == y);
    }
}

interface erc20 {
    function transfer(address recipient, uint amount) external returns (bool);
    function balanceOf(address) external view returns (uint);
    function transferFrom(address sender, address recipient, uint amount) external returns (bool);
}

contract Keep3rOptions is ERC721Enumerable {
    string public constant name = "Keep3r Options";
    string public constant symbol = "oKP3R";
    address immutable rKP3R;

    constructor() {
        rKP3R = msg.sender;
    }

    function mint(address _user, uint _id) external returns (bool) {
        require(msg.sender == rKP3R);
        _safeMint(_user, _id);
        return true;
    }

    function burn(uint _id) external returns (bool) {
        require(msg.sender == rKP3R);
        _burn(_id);
        return true;
    }

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

contract RedeemableKeep3r {
    string public constant name = "Redeemable Keep3r";
    string public constant symbol = "rKP3R";
    uint8 public constant decimals = 18;

    address public gov;
    address public nextGov;
    uint public delayGov;

    uint public discount = 50;
    uint public nextDiscount;
    uint public delayDiscount;

    address public treasury;
    address public nextTreasury;
    uint public delayTreasury;

    struct option {
        uint amount;
        uint strike;
        uint expiry;
        bool exercised;
    }

    option[] public options;
    uint public nextIndex;

    address constant KP3R = address(0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44);
    address constant USDC = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
    address constant UNIv3 = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    uint32 constant TWAP_PERIOD = 86400;
    uint32 constant TWAP_NOW = 60;
    uint32 constant OPTION_EXPIRY = 1 days;
    uint32 constant DELAY = 1 days;
    uint32 constant BASE = 100;
    Keep3rOptions immutable public oKP3R;

    event Created(address indexed owner, uint amount, uint strike, uint expiry, uint id);
    event Redeem(address indexed from, address indexed owner, uint amount, uint strike, uint id);
    event Refund(address indexed from, address indexed owner, uint amount, uint strike, uint id);

    constructor(address _treasury) {
        gov = msg.sender;
        treasury = _treasury;
        oKP3R = new Keep3rOptions();
    }

    modifier g() {
        require(msg.sender == gov);
        _;
    }

    function setGov(address _gov) external g {
        nextGov = _gov;
        delayGov = block.timestamp + DELAY;
    }

    function acceptGov() external {
        require(msg.sender == nextGov && delayGov < block.timestamp);
        gov = nextGov;
    }

    function setDiscount(uint _discount) external g {
        nextDiscount = _discount;
        delayDiscount = block.timestamp + DELAY;
    }

    function commitDiscount() external g {
        require(delayDiscount < block.timestamp);
        discount = nextDiscount;
    }

    function setTreasury(address _treasury) external g {
        nextTreasury = _treasury;
        delayTreasury = block.timestamp + DELAY;
    }

    function commitTreasury() external g {
        require(delayTreasury < block.timestamp);
        treasury = nextTreasury;
    }

    /// @notice Total number of tokens in circulation
    uint public totalSupply = 0;

    mapping(address => mapping (address => uint)) public allowance;
    mapping(address => uint) public balanceOf;

    event Transfer(address indexed from, address indexed to, uint amount);
    event Approval(address indexed owner, address indexed spender, uint amount);

    function refund(uint[] memory _ids) external {
        for (uint i = 0; i < _ids.length; i++) {
            option storage _opt = options[_ids[i]];
            if (_opt.expiry < block.timestamp && !_opt.exercised) {
                _opt.exercised = true;
                _safeTransfer(KP3R, treasury, _opt.amount);
                address _owner = oKP3R.ownerOf(_ids[i]);
                oKP3R.burn(_ids[i]);
                emit Refund(msg.sender, _owner, _opt.amount, _opt.strike, _ids[i]);
            }
        }
    }

    function _fetchTwap(
        address _tokenIn,
        address _tokenOut,
        uint24 _poolFee,
        uint32 _twapPeriod,
        uint _amountIn
    ) internal view returns (uint256 amountOut) {
        address pool =
            PoolAddress.computeAddress(UNIv3, PoolAddress.getPoolKey(_tokenIn, _tokenOut, _poolFee));
        // Leave twapTick as a int256 to avoid solidity casting
        int256 twapTick = OracleLibrary.consult(pool, _twapPeriod);
        return
            OracleLibrary.getQuoteAtTick(
                int24(twapTick), // can assume safe being result from consult()
                SafeUint128.toUint128(_amountIn),
                _tokenIn,
                _tokenOut
            );
    }

    function assetToAsset(
        address _tokenIn,
        uint _amountIn,
        address _tokenOut,
        uint32 _twapPeriod
    ) public view returns (uint ethAmountOut) {
        uint256 ethAmount = assetToEth(_tokenIn, _amountIn, _twapPeriod);
        return ethToAsset(ethAmount, _tokenOut, _twapPeriod);
    }

    function assetToEth(
        address _tokenIn,
        uint _amountIn,
        uint32 _twapPeriod
    ) public view returns (uint ethAmountOut) {
        return _fetchTwap(_tokenIn, WETH, 10000, _twapPeriod, _amountIn);
    }

    function ethToAsset(
        uint _ethAmountIn,
        address _tokenOut,
        uint32 _twapPeriod
    ) public view returns (uint256 amountOut) {
        return _fetchTwap(WETH, _tokenOut, 3000, _twapPeriod, _ethAmountIn);
    }

    function price() external view returns (uint) {
        return assetToAsset(KP3R, 1e18, USDC, TWAP_PERIOD);
    }

    function twap() external view returns (uint) {
        return assetToAsset(KP3R, 1e18, USDC, TWAP_NOW);
    }

    function calc(uint amount) public view returns (uint) {
        uint _strike = assetToAsset(KP3R, amount, USDC, TWAP_PERIOD);
        uint _price = assetToAsset(KP3R, amount, USDC, TWAP_NOW);
        _strike = _strike * discount / BASE;
        _price = _price * discount / BASE;
        return _strike > _price ? _strike : _price;
    }

    function deposit(uint _amount) external returns (bool) {
        _safeTransferFrom(KP3R, msg.sender, address(this), _amount);
        _mint(msg.sender, _amount);
        return true;
    }

    function claim() external returns (uint) {
        uint _amount = balanceOf[msg.sender];
        _burn(msg.sender, _amount);
        return _claim(_amount);
    }

    function claim(uint amount) external returns (uint) {
        _burn(msg.sender, amount);
        return _claim(amount);
    }

    function _claim(uint amount) internal returns (uint) {
        uint _strike = calc(amount);
        uint _expiry = block.timestamp + OPTION_EXPIRY;
        options.push(option(amount, _strike, _expiry, false));
        oKP3R.mint(msg.sender, nextIndex);
        emit Created(msg.sender, amount, _strike, _expiry, nextIndex);
        return nextIndex++;
    }

    function redeem(uint id) external {
        require(oKP3R.isApprovedOrOwner(msg.sender, id));
        option storage _opt = options[id];
        require(_opt.expiry >= block.timestamp && !_opt.exercised);
        _opt.exercised = true;
        _safeTransferFrom(USDC, msg.sender, treasury, _opt.strike);
        _safeTransfer(KP3R, msg.sender, _opt.amount);
        oKP3R.burn(id);
        emit Redeem(msg.sender, msg.sender, _opt.amount, _opt.strike, id);
    }

    function _mint(address to, uint amount) internal {
        // mint the amount
        totalSupply += amount;
        // transfer the amount to the recipient
        balanceOf[to] += amount;
        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint amount) internal {
        // burn the amount
        totalSupply -= amount;
        // transfer the amount from the recipient
        balanceOf[from] -= amount;
        emit Transfer(from, address(0), amount);
    }

    function approve(address spender, uint amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transfer(address dst, uint amount) external returns (bool) {
        _transferTokens(msg.sender, dst, amount);
        return true;
    }

    function transferFrom(address src, address dst, uint amount) external returns (bool) {
        address spender = msg.sender;
        uint spenderAllowance = allowance[src][spender];

        if (spender != src && spenderAllowance != type(uint).max) {
            uint newAllowance = spenderAllowance - amount;
            allowance[src][spender] = newAllowance;

            emit Approval(src, spender, newAllowance);
        }

        _transferTokens(src, dst, amount);
        return true;
    }

    function _transferTokens(address src, address dst, uint amount) internal {
        balanceOf[src] -= amount;
        balanceOf[dst] += amount;

        emit Transfer(src, dst, amount);
    }

    function _safeTransfer(address token, address to, uint256 value) internal {
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(erc20.transfer.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))));
    }

    function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(erc20.transferFrom.selector, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))));
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"isApprovedOrOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801561001057600080fd5b5033606081901b60805261162a610039600039600081816105ad0152610612015261162a6000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806342966c68116100a257806370a082311161007157806370a082311461026757806395d89b411461027a578063a22cb4651461029e578063b88d4fde146102b1578063e985e9c5146102c457600080fd5b806342966c681461021b578063430c20811461022e5780634f6ccce7146102415780636352211e1461025457600080fd5b806318160ddd116100e957806318160ddd146101bd57806323b872dd146101cf5780632f745c59146101e257806340c10f19146101f557806342842e0e1461020857600080fd5b806301ffc9a71461011b57806306fdde0314610143578063081812fc1461017d578063095ea7b3146101a8575b600080fd5b61012e6101293660046113c1565b6102d7565b60405190151581526020015b60405180910390f35b6101706040518060400160405280600e81526020016d4b6565703372204f7074696f6e7360901b81525081565b60405161013a919061149e565b61019061018b3660046113fb565b610329565b6040516001600160a01b03909116815260200161013a565b6101bb6101b6366004611397565b6103c3565b005b6006545b60405190815260200161013a565b6101bb6101dd366004611243565b6104d9565b6101c16101f0366004611397565b61050a565b61012e610203366004611397565b6105a0565b6101bb610216366004611243565b6105ea565b61012e6102293660046113fb565b610605565b61012e61023c366004611397565b61064d565b6101c161024f3660046113fb565b610660565b6101906102623660046113fb565b6106f3565b6101c16102753660046111f5565b61076a565b6101706040518060400160405280600581526020016437a5a819a960d91b81525081565b6101bb6102ac36600461135b565b6107f1565b6101bb6102bf36600461127f565b6108b6565b61012e6102d2366004611210565b6108ee565b60006001600160e01b031982166380ac58cd60e01b148061030857506001600160e01b03198216635b5e139f60e01b145b8061032357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000818152602081905260408120546001600160a01b03166103a75760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600260205260409020546001600160a01b031690565b60006103ce826106f3565b9050806001600160a01b0316836001600160a01b0316141561043c5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161039e565b336001600160a01b0382161480610458575061045881336108ee565b6104ca5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161039e565b6104d4838361091c565b505050565b6104e3338261098a565b6104ff5760405162461bcd60e51b815260040161039e90611503565b6104d4838383610a61565b60006105158361076a565b82106105775760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161039e565b506001600160a01b03919091166000908152600460209081526040808320938352929052205490565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105d757600080fd5b6105e18383610c10565b50600192915050565b6104d4838383604051806020016040528060008152506108b6565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461063c57600080fd5b61064582610c2e565b506001919050565b6000610659838361098a565b9392505050565b600061066b60065490565b82106106ce5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161039e565b600682815481106106e1576106e16115af565b90600052602060002001549050919050565b6000818152602081905260408120546001600160a01b0316806103235760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161039e565b60006001600160a01b0382166107d55760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161039e565b506001600160a01b031660009081526001602052604090205490565b6001600160a01b03821633141561084a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161039e565b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6108c0338361098a565b6108dc5760405162461bcd60e51b815260040161039e90611503565b6108e884848484610cd7565b50505050565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b600081815260026020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610951826106f3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152602081905260408120546001600160a01b0316610a035760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161039e565b6000610a0e836106f3565b9050806001600160a01b0316846001600160a01b03161480610a495750836001600160a01b0316610a3e84610329565b6001600160a01b0316145b80610a595750610a5981856108ee565b949350505050565b826001600160a01b0316610a74826106f3565b6001600160a01b031614610adc5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161039e565b6001600160a01b038216610b3e5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161039e565b610b49838383610d0a565b610b5460008261091c565b6001600160a01b03831660009081526001602081905260408220805491929091610b7f90849061156c565b90915550506001600160a01b03821660009081526001602081905260408220805491929091610baf908490611554565b909155505060008181526020819052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b610c2a828260405180602001604052806000815250610dc2565b5050565b6000610c39826106f3565b9050610c4781600084610d0a565b610c5260008361091c565b6001600160a01b03811660009081526001602081905260408220805491929091610c7d90849061156c565b909155505060008281526020819052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610ce2848484610a61565b610cee84848484610df5565b6108e85760405162461bcd60e51b815260040161039e906114b1565b6001600160a01b038316610d6557610d6081600680546000838152600760205260408120829055600182018355919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0155565b610d88565b816001600160a01b0316836001600160a01b031614610d8857610d888382610ef9565b6001600160a01b038216610d9f576104d481610f96565b826001600160a01b0316826001600160a01b0316146104d4576104d48282611045565b610dcc8383611089565b610dd96000848484610df5565b6104d45760405162461bcd60e51b815260040161039e906114b1565b6000833b15610eee57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290610e30903390899088908890600401611461565b602060405180830381600087803b158015610e4a57600080fd5b505af1925050508015610e7a575060408051601f3d908101601f19168201909252610e77918101906113de565b60015b610ed4573d808015610ea8576040519150601f19603f3d011682016040523d82523d6000602084013e610ead565b606091505b508051610ecc5760405162461bcd60e51b815260040161039e906114b1565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610a59565b506001949350505050565b60006001610f068461076a565b610f10919061156c565b600083815260056020526040902054909150808214610f63576001600160a01b03841660009081526004602090815260408083208584528252808320548484528184208190558352600590915290208190555b5060009182526005602090815260408084208490556001600160a01b039094168352600481528383209183525290812055565b600654600090610fa89060019061156c565b60008381526007602052604081205460068054939450909284908110610fd057610fd06115af565b906000526020600020015490508060068381548110610ff157610ff16115af565b600091825260208083209091019290925582815260079091526040808220849055858252812055600680548061102957611029611599565b6001900381819060005260206000200160009055905550505050565b60006110508361076a565b6001600160a01b039093166000908152600460209081526040808320868452825280832085905593825260059052919091209190915550565b6001600160a01b0382166110df5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161039e565b6000818152602081905260409020546001600160a01b0316156111445760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161039e565b61115060008383610d0a565b6001600160a01b0382166000908152600160208190526040822080549192909161117b908490611554565b909155505060008181526020819052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b80356001600160a01b03811681146111f057600080fd5b919050565b60006020828403121561120757600080fd5b610659826111d9565b6000806040838503121561122357600080fd5b61122c836111d9565b915061123a602084016111d9565b90509250929050565b60008060006060848603121561125857600080fd5b611261846111d9565b925061126f602085016111d9565b9150604084013590509250925092565b6000806000806080858703121561129557600080fd5b61129e856111d9565b93506112ac602086016111d9565b925060408501359150606085013567ffffffffffffffff808211156112d057600080fd5b818701915087601f8301126112e457600080fd5b8135818111156112f6576112f66115c5565b604051601f8201601f19908116603f0116810190838211818310171561131e5761131e6115c5565b816040528281528a602084870101111561133757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561136e57600080fd5b611377836111d9565b91506020830135801515811461138c57600080fd5b809150509250929050565b600080604083850312156113aa57600080fd5b6113b3836111d9565b946020939093013593505050565b6000602082840312156113d357600080fd5b8135610659816115db565b6000602082840312156113f057600080fd5b8151610659816115db565b60006020828403121561140d57600080fd5b5035919050565b6000815180845260005b8181101561143a5760208185018101518683018201520161141e565b8181111561144c576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061149490830184611414565b9695505050505050565b6020815260006106596020830184611414565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000821982111561156757611567611583565b500190565b60008282101561157e5761157e611583565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146115f157600080fd5b5056fea2646970667358221220377eb001f223e1fcaa8a9f3f493f41c06118872dfc6c2f891c73471e4b2c7fac64736f6c63430008070033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101165760003560e01c806342966c68116100a257806370a082311161007157806370a082311461026757806395d89b411461027a578063a22cb4651461029e578063b88d4fde146102b1578063e985e9c5146102c457600080fd5b806342966c681461021b578063430c20811461022e5780634f6ccce7146102415780636352211e1461025457600080fd5b806318160ddd116100e957806318160ddd146101bd57806323b872dd146101cf5780632f745c59146101e257806340c10f19146101f557806342842e0e1461020857600080fd5b806301ffc9a71461011b57806306fdde0314610143578063081812fc1461017d578063095ea7b3146101a8575b600080fd5b61012e6101293660046113c1565b6102d7565b60405190151581526020015b60405180910390f35b6101706040518060400160405280600e81526020016d4b6565703372204f7074696f6e7360901b81525081565b60405161013a919061149e565b61019061018b3660046113fb565b610329565b6040516001600160a01b03909116815260200161013a565b6101bb6101b6366004611397565b6103c3565b005b6006545b60405190815260200161013a565b6101bb6101dd366004611243565b6104d9565b6101c16101f0366004611397565b61050a565b61012e610203366004611397565b6105a0565b6101bb610216366004611243565b6105ea565b61012e6102293660046113fb565b610605565b61012e61023c366004611397565b61064d565b6101c161024f3660046113fb565b610660565b6101906102623660046113fb565b6106f3565b6101c16102753660046111f5565b61076a565b6101706040518060400160405280600581526020016437a5a819a960d91b81525081565b6101bb6102ac36600461135b565b6107f1565b6101bb6102bf36600461127f565b6108b6565b61012e6102d2366004611210565b6108ee565b60006001600160e01b031982166380ac58cd60e01b148061030857506001600160e01b03198216635b5e139f60e01b145b8061032357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000818152602081905260408120546001600160a01b03166103a75760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600260205260409020546001600160a01b031690565b60006103ce826106f3565b9050806001600160a01b0316836001600160a01b0316141561043c5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161039e565b336001600160a01b0382161480610458575061045881336108ee565b6104ca5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161039e565b6104d4838361091c565b505050565b6104e3338261098a565b6104ff5760405162461bcd60e51b815260040161039e90611503565b6104d4838383610a61565b60006105158361076a565b82106105775760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161039e565b506001600160a01b03919091166000908152600460209081526040808320938352929052205490565b6000336001600160a01b037f000000000000000000000000edb67ee1b171c4ec66e6c10ec43edbba20fae8e916146105d757600080fd5b6105e18383610c10565b50600192915050565b6104d4838383604051806020016040528060008152506108b6565b6000336001600160a01b037f000000000000000000000000edb67ee1b171c4ec66e6c10ec43edbba20fae8e9161461063c57600080fd5b61064582610c2e565b506001919050565b6000610659838361098a565b9392505050565b600061066b60065490565b82106106ce5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161039e565b600682815481106106e1576106e16115af565b90600052602060002001549050919050565b6000818152602081905260408120546001600160a01b0316806103235760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161039e565b60006001600160a01b0382166107d55760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161039e565b506001600160a01b031660009081526001602052604090205490565b6001600160a01b03821633141561084a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161039e565b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6108c0338361098a565b6108dc5760405162461bcd60e51b815260040161039e90611503565b6108e884848484610cd7565b50505050565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b600081815260026020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610951826106f3565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152602081905260408120546001600160a01b0316610a035760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161039e565b6000610a0e836106f3565b9050806001600160a01b0316846001600160a01b03161480610a495750836001600160a01b0316610a3e84610329565b6001600160a01b0316145b80610a595750610a5981856108ee565b949350505050565b826001600160a01b0316610a74826106f3565b6001600160a01b031614610adc5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161039e565b6001600160a01b038216610b3e5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161039e565b610b49838383610d0a565b610b5460008261091c565b6001600160a01b03831660009081526001602081905260408220805491929091610b7f90849061156c565b90915550506001600160a01b03821660009081526001602081905260408220805491929091610baf908490611554565b909155505060008181526020819052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b610c2a828260405180602001604052806000815250610dc2565b5050565b6000610c39826106f3565b9050610c4781600084610d0a565b610c5260008361091c565b6001600160a01b03811660009081526001602081905260408220805491929091610c7d90849061156c565b909155505060008281526020819052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610ce2848484610a61565b610cee84848484610df5565b6108e85760405162461bcd60e51b815260040161039e906114b1565b6001600160a01b038316610d6557610d6081600680546000838152600760205260408120829055600182018355919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0155565b610d88565b816001600160a01b0316836001600160a01b031614610d8857610d888382610ef9565b6001600160a01b038216610d9f576104d481610f96565b826001600160a01b0316826001600160a01b0316146104d4576104d48282611045565b610dcc8383611089565b610dd96000848484610df5565b6104d45760405162461bcd60e51b815260040161039e906114b1565b6000833b15610eee57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290610e30903390899088908890600401611461565b602060405180830381600087803b158015610e4a57600080fd5b505af1925050508015610e7a575060408051601f3d908101601f19168201909252610e77918101906113de565b60015b610ed4573d808015610ea8576040519150601f19603f3d011682016040523d82523d6000602084013e610ead565b606091505b508051610ecc5760405162461bcd60e51b815260040161039e906114b1565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610a59565b506001949350505050565b60006001610f068461076a565b610f10919061156c565b600083815260056020526040902054909150808214610f63576001600160a01b03841660009081526004602090815260408083208584528252808320548484528184208190558352600590915290208190555b5060009182526005602090815260408084208490556001600160a01b039094168352600481528383209183525290812055565b600654600090610fa89060019061156c565b60008381526007602052604081205460068054939450909284908110610fd057610fd06115af565b906000526020600020015490508060068381548110610ff157610ff16115af565b600091825260208083209091019290925582815260079091526040808220849055858252812055600680548061102957611029611599565b6001900381819060005260206000200160009055905550505050565b60006110508361076a565b6001600160a01b039093166000908152600460209081526040808320868452825280832085905593825260059052919091209190915550565b6001600160a01b0382166110df5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161039e565b6000818152602081905260409020546001600160a01b0316156111445760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161039e565b61115060008383610d0a565b6001600160a01b0382166000908152600160208190526040822080549192909161117b908490611554565b909155505060008181526020819052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b80356001600160a01b03811681146111f057600080fd5b919050565b60006020828403121561120757600080fd5b610659826111d9565b6000806040838503121561122357600080fd5b61122c836111d9565b915061123a602084016111d9565b90509250929050565b60008060006060848603121561125857600080fd5b611261846111d9565b925061126f602085016111d9565b9150604084013590509250925092565b6000806000806080858703121561129557600080fd5b61129e856111d9565b93506112ac602086016111d9565b925060408501359150606085013567ffffffffffffffff808211156112d057600080fd5b818701915087601f8301126112e457600080fd5b8135818111156112f6576112f66115c5565b604051601f8201601f19908116603f0116810190838211818310171561131e5761131e6115c5565b816040528281528a602084870101111561133757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561136e57600080fd5b611377836111d9565b91506020830135801515811461138c57600080fd5b809150509250929050565b600080604083850312156113aa57600080fd5b6113b3836111d9565b946020939093013593505050565b6000602082840312156113d357600080fd5b8135610659816115db565b6000602082840312156113f057600080fd5b8151610659816115db565b60006020828403121561140d57600080fd5b5035919050565b6000815180845260005b8181101561143a5760208185018101518683018201520161141e565b8181111561144c576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061149490830184611414565b9695505050505050565b6020815260006106596020830184611414565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000821982111561156757611567611583565b500190565b60008282101561157e5761157e611583565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146115f157600080fd5b5056fea2646970667358221220377eb001f223e1fcaa8a9f3f493f41c06118872dfc6c2f891c73471e4b2c7fac64736f6c63430008070033

Deployed Bytecode Sourcemap

29925:698:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2871:305;;;;;;:::i;:::-;;:::i;:::-;;;4766:14:1;;4759:22;4741:41;;4729:2;4714:18;2871:305:0;;;;;;;;29975:46;;;;;;;;;;;;;-1:-1:-1;;;29975:46:0;;;;;;;;;;;;;;;:::i;4164:221::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;4064:32:1;;;;4046:51;;4034:2;4019:18;4164:221:0;3900:203:1;3749:407:0;;;;;;:::i;:::-;;:::i;:::-;;15779:113;15867:10;:17;15779:113;;;11186:25:1;;;11174:2;11159:18;15779:113:0;11040:177:1;5067:337:0;;;;;;:::i;:::-;;:::i;15447:256::-;;;;;;:::i;:::-;;:::i;30165:164::-;;;;;;:::i;:::-;;:::i;5412:185::-;;;;;;:::i;:::-;;:::i;30337:138::-;;;;;;:::i;:::-;;:::i;30483:137::-;;;;;;:::i;:::-;;:::i;15969:233::-;;;;;;:::i;:::-;;:::i;3400:239::-;;;;;;:::i;:::-;;:::i;3184:208::-;;;;;;:::i;:::-;;:::i;30028:39::-;;;;;;;;;;;;;-1:-1:-1;;;30028:39:0;;;;;;;;4393:289;;;;;;:::i;:::-;;:::i;5668:326::-;;;;;;:::i;:::-;;:::i;4895:164::-;;;;;;:::i;:::-;-1:-1:-1;;;;;5016:25:0;;;4992:4;5016:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;4895:164;2871:305;2973:4;-1:-1:-1;;;;;;;;;3010:40:0;;;;:105;;-1:-1:-1;;;;;;;;;;3067:48:0;;;3010:105;:158;;;-1:-1:-1;;;;;;;2254:40:0;;-1:-1:-1;;;2254:40:0;3132:36;2990:178;2871:305;-1:-1:-1;;2871:305:0:o;4164:221::-;4240:7;7593:16;;;;;;;;;;;-1:-1:-1;;;;;7593:16:0;4260:73;;;;-1:-1:-1;;;4260:73:0;;9186:2:1;4260:73:0;;;9168:21:1;9225:2;9205:18;;;9198:30;9264:34;9244:18;;;9237:62;-1:-1:-1;;;9315:18:1;;;9308:42;9367:19;;4260:73:0;;;;;;;;;-1:-1:-1;4353:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;4353:24:0;;4164:221::o;3749:407::-;3830:13;3846:23;3861:7;3846:14;:23::i;:::-;3830:39;-1:-1:-1;;;;;;3888:11:0;;;;;;;;3880:57;;;;-1:-1:-1;;;3880:57:0;;10009:2:1;3880:57:0;;;9991:21:1;10048:2;10028:18;;;10021:30;10087:34;10067:18;;;10060:62;-1:-1:-1;;;10138:18:1;;;10131:31;10179:19;;3880:57:0;9807:397:1;3880:57:0;-1:-1:-1;;;;;3972:19:0;;:10;:19;;:58;;-1:-1:-1;;;;;;5016:25:0;;4992:4;5016:25;;;:18;:25;;;;;;;;4019:10;5016:35;;;;;;;;;;3995;3950:164;;;;-1:-1:-1;;;3950:164:0;;7579:2:1;3950:164:0;;;7561:21:1;7618:2;7598:18;;;7591:30;7657:34;7637:18;;;7630:62;7728:26;7708:18;;;7701:54;7772:19;;3950:164:0;7377:420:1;3950:164:0;4127:21;4136:2;4140:7;4127:8;:21::i;:::-;3819:337;3749:407;;:::o;5067:337::-;5262:39;5281:10;5293:7;5262:18;:39::i;:::-;5254:101;;;;-1:-1:-1;;;5254:101:0;;;;;;;:::i;:::-;5368:28;5378:4;5384:2;5388:7;5368:9;:28::i;15447:256::-;15544:7;15580:23;15597:5;15580:16;:23::i;:::-;15572:5;:31;15564:87;;;;-1:-1:-1;;;15564:87:0;;5219:2:1;15564:87:0;;;5201:21:1;5258:2;5238:18;;;5231:30;5297:34;5277:18;;;5270:62;-1:-1:-1;;;5348:18:1;;;5341:41;5399:19;;15564:87:0;5017:407:1;15564:87:0;-1:-1:-1;;;;;;15669:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;15447:256::o;30165:164::-;30222:4;30261:5;-1:-1:-1;;;;;30247:19:0;:10;:19;30239:28;;;;;;30278:21;30288:5;30295:3;30278:9;:21::i;:::-;-1:-1:-1;30317:4:0;30165:164;;;;:::o;5412:185::-;5550:39;5567:4;5573:2;5577:7;5550:39;;;;;;;;;;;;:16;:39::i;30337:138::-;30379:4;30418:5;-1:-1:-1;;;;;30404:19:0;:10;:19;30396:28;;;;;;30435:10;30441:3;30435:5;:10::i;:::-;-1:-1:-1;30463:4:0;;30337:138;-1:-1:-1;30337:138:0:o;30483:137::-;30558:4;30582:30;30601:5;30608:3;30582:18;:30::i;:::-;30575:37;30483:137;-1:-1:-1;;;30483:137:0:o;15969:233::-;16044:7;16080:30;15867:10;:17;;15779:113;16080:30;16072:5;:38;16064:95;;;;-1:-1:-1;;;16064:95:0;;10829:2:1;16064:95:0;;;10811:21:1;10868:2;10848:18;;;10841:30;10907:34;10887:18;;;10880:62;-1:-1:-1;;;10958:18:1;;;10951:42;11010:19;;16064:95:0;10627:408:1;16064:95:0;16177:10;16188:5;16177:17;;;;;;;;:::i;:::-;;;;;;;;;16170:24;;15969:233;;;:::o;3400:239::-;3472:7;3508:16;;;;;;;;;;;-1:-1:-1;;;;;3508:16:0;;3535:73;;;;-1:-1:-1;;;3535:73:0;;8415:2:1;3535:73:0;;;8397:21:1;8454:2;8434:18;;;8427:30;8493:34;8473:18;;;8466:62;-1:-1:-1;;;8544:18:1;;;8537:39;8593:19;;3535:73:0;8213:405:1;3184:208:0;3256:7;-1:-1:-1;;;;;3284:19:0;;3276:74;;;;-1:-1:-1;;;3276:74:0;;8004:2:1;3276:74:0;;;7986:21:1;8043:2;8023:18;;;8016:30;8082:34;8062:18;;;8055:62;-1:-1:-1;;;8133:18:1;;;8126:40;8183:19;;3276:74:0;7802:406:1;3276:74:0;-1:-1:-1;;;;;;3368:16:0;;;;;-1:-1:-1;3368:16:0;;;;;;;3184:208::o;4393:289::-;4508:10;-1:-1:-1;;;;;4496:22:0;;;;4488:60;;;;-1:-1:-1;;;4488:60:0;;6812:2:1;4488:60:0;;;6794:21:1;6851:2;6831:18;;;6824:30;6890:27;6870:18;;;6863:55;6935:18;;4488:60:0;6610:349:1;4488:60:0;4580:10;4561:30;;;;:18;:30;;;;;;;;-1:-1:-1;;;;;4561:40:0;;;;;;;;;;;;:51;;-1:-1:-1;;4561:51:0;;;;;;;;;;4628:46;;4741:41:1;;;4628:46:0;;4561:40;;4580:10;4628:46;;;;;;;;;;;4393:289;;:::o;5668:326::-;5843:39;5862:10;5874:7;5843:18;:39::i;:::-;5835:101;;;;-1:-1:-1;;;5835:101:0;;;;;;;:::i;:::-;5947:39;5961:4;5967:2;5971:7;5980:5;5947:13;:39::i;:::-;5668:326;;;;:::o;11486:174::-;11561:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;11561:29:0;-1:-1:-1;;;;;11561:29:0;;;;;;;;:24;;11615:23;11561:24;11615:14;:23::i;:::-;11606:46;;-1:-1:-1;;;;;11606:46:0;;;;;;;;;;11486:174;;:::o;7798:348::-;7891:4;7593:16;;;;;;;;;;;-1:-1:-1;;;;;7593:16:0;7908:73;;;;-1:-1:-1;;;7908:73:0;;7166:2:1;7908:73:0;;;7148:21:1;7205:2;7185:18;;;7178:30;7244:34;7224:18;;;7217:62;-1:-1:-1;;;7295:18:1;;;7288:42;7347:19;;7908:73:0;6964:408:1;7908:73:0;7992:13;8008:23;8023:7;8008:14;:23::i;:::-;7992:39;-1:-1:-1;;;;;;8050:16:0;;;;;;;;:51;;-1:-1:-1;;;;;;8070:31:0;;:20;8082:7;8070:11;:20::i;:::-;-1:-1:-1;;;;;8070:31:0;;8050:51;:87;;;-1:-1:-1;;;;;;5016:25:0;;;4992:4;5016:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;8105:32;8042:96;7798:348;-1:-1:-1;;;;7798:348:0:o;10790:578::-;-1:-1:-1;;;;;10922:31:0;;:23;10937:7;10922:14;:23::i;:::-;-1:-1:-1;;;;;10922:31:0;;10914:85;;;;-1:-1:-1;;;10914:85:0;;9599:2:1;10914:85:0;;;9581:21:1;9638:2;9618:18;;;9611:30;9677:34;9657:18;;;9650:62;-1:-1:-1;;;9728:18:1;;;9721:39;9777:19;;10914:85:0;9397:405:1;10914:85:0;-1:-1:-1;;;;;11018:16:0;;11010:65;;;;-1:-1:-1;;;11010:65:0;;6407:2:1;11010:65:0;;;6389:21:1;6446:2;6426:18;;;6419:30;6485:34;6465:18;;;6458:62;-1:-1:-1;;;6536:18:1;;;6529:34;6580:19;;11010:65:0;6205:400:1;11010:65:0;11088:39;11109:4;11115:2;11119:7;11088:20;:39::i;:::-;11192:29;11209:1;11213:7;11192:8;:29::i;:::-;-1:-1:-1;;;;;11234:15:0;;;;;;-1:-1:-1;11234:15:0;;;;;;;:20;;-1:-1:-1;;11234:15:0;;:20;;-1:-1:-1;;11234:20:0;:::i;:::-;;;;-1:-1:-1;;;;;;;11265:13:0;;;;;;-1:-1:-1;11265:13:0;;;;;;;:18;;-1:-1:-1;;11265:13:0;;:18;;-1:-1:-1;;11265:18:0;:::i;:::-;;;;-1:-1:-1;;11294:7:0;:16;;;;;;;;;;;:21;;-1:-1:-1;;;;;;11294:21:0;-1:-1:-1;;;;;11294:21:0;;;;;;;;;11333:27;;11294:16;;11333:27;;;;;;;10790:578;;;:::o;8488:110::-;8564:26;8574:2;8578:7;8564:26;;;;;;;;;;;;:9;:26::i;:::-;8488:110;;:::o;10093:360::-;10153:13;10169:23;10184:7;10169:14;:23::i;:::-;10153:39;;10205:48;10226:5;10241:1;10245:7;10205:20;:48::i;:::-;10294:29;10311:1;10315:7;10294:8;:29::i;:::-;-1:-1:-1;;;;;10336:16:0;;;;;;-1:-1:-1;10336:16:0;;;;;;;:21;;-1:-1:-1;;10336:16:0;;:21;;-1:-1:-1;;10336:21:0;:::i;:::-;;;;-1:-1:-1;;10375:7:0;:16;;;;;;;;;;;10368:23;;-1:-1:-1;;;;;;10368:23:0;;;10409:36;10375:16;;:7;-1:-1:-1;;;;;10409:36:0;;;;;10375:7;;10409:36;10142:311;10093:360;:::o;6876:315::-;7033:28;7043:4;7049:2;7053:7;7033:9;:28::i;:::-;7080:48;7103:4;7109:2;7113:7;7122:5;7080:22;:48::i;:::-;7072:111;;;;-1:-1:-1;;;7072:111:0;;;;;;;:::i;16815:589::-;-1:-1:-1;;;;;17021:18:0;;17017:187;;17056:40;17088:7;18231:10;:17;;18204:24;;;;:15;:24;;;;;:44;;;18259:24;;;;;;;;;;;;18127:164;17056:40;17017:187;;;-1:-1:-1;;;;;17118:10:0;;;;;;;17114:90;;17145:47;17178:4;17184:7;17145:32;:47::i;:::-;-1:-1:-1;;;;;17218:16:0;;17214:183;;17251:45;17288:7;17251:36;:45::i;17214:183::-;-1:-1:-1;;;;;17318:10:0;;;;;;;17314:83;;17345:40;17373:2;17377:7;17345:27;:40::i;8825:321::-;8955:18;8961:2;8965:7;8955:5;:18::i;:::-;9006:54;9037:1;9041:2;9045:7;9054:5;9006:22;:54::i;:::-;8984:154;;;;-1:-1:-1;;;8984:154:0;;;;;;;:::i;12225:801::-;12380:4;4823:20;;4871:8;12397:622;;12437:70;;-1:-1:-1;;;12437:70:0;;-1:-1:-1;;;;;12437:36:0;;;;;:70;;12474:10;;12486:4;;12492:7;;12501:5;;12437:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12437:70:0;;;;;;;;-1:-1:-1;;12437:70:0;;;;;;;;;;;;:::i;:::-;;;12433:531;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12681:13:0;;12677:272;;12724:60;;-1:-1:-1;;;12724:60:0;;;;;;;:::i;12677:272::-;12899:6;12893:13;12884:6;12880:2;12876:15;12869:38;12433:531;-1:-1:-1;;;;;;12558:55:0;-1:-1:-1;;;12558:55:0;;-1:-1:-1;12551:62:0;;12397:622;-1:-1:-1;13003:4:0;12225:801;;;;;;:::o;18918:988::-;19184:22;19234:1;19209:22;19226:4;19209:16;:22::i;:::-;:26;;;;:::i;:::-;19246:18;19267:26;;;:17;:26;;;;;;19184:51;;-1:-1:-1;19400:28:0;;;19396:328;;-1:-1:-1;;;;;19467:18:0;;19445:19;19467:18;;;:12;:18;;;;;;;;:34;;;;;;;;;19518:30;;;;;;:44;;;19635:30;;:17;:30;;;;;:43;;;19396:328;-1:-1:-1;19820:26:0;;;;:17;:26;;;;;;;;19813:33;;;-1:-1:-1;;;;;19864:18:0;;;;;;:12;:18;;;;;:34;;;;;;;19857:41;18918:988::o;20201:1079::-;20479:10;:17;20454:22;;20479:21;;20499:1;;20479:21;:::i;:::-;20511:18;20532:24;;;:15;:24;;;;;;20905:10;:26;;20454:46;;-1:-1:-1;20532:24:0;;20454:46;;20905:26;;;;;;:::i;:::-;;;;;;;;;20883:48;;20969:11;20944:10;20955;20944:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;21049:28;;;:15;:28;;;;;;;:41;;;21221:24;;;;;21214:31;21256:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;20272:1008;;;20201:1079;:::o;17705:221::-;17790:14;17807:20;17824:2;17807:16;:20::i;:::-;-1:-1:-1;;;;;17838:16:0;;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;17883:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;17705:221:0:o;9482:382::-;-1:-1:-1;;;;;9562:16:0;;9554:61;;;;-1:-1:-1;;;9554:61:0;;8825:2:1;9554:61:0;;;8807:21:1;;;8844:18;;;8837:30;8903:34;8883:18;;;8876:62;8955:18;;9554:61:0;8623:356:1;9554:61:0;7569:4;7593:16;;;;;;;;;;;-1:-1:-1;;;;;7593:16:0;:30;9626:58;;;;-1:-1:-1;;;9626:58:0;;6050:2:1;9626:58:0;;;6032:21:1;6089:2;6069:18;;;6062:30;6128;6108:18;;;6101:58;6176:18;;9626:58:0;5848:352:1;9626:58:0;9697:45;9726:1;9730:2;9734:7;9697:20;:45::i;:::-;-1:-1:-1;;;;;9755:13:0;;;;;;-1:-1:-1;9755:13:0;;;;;;;:18;;-1:-1:-1;;9755:13:0;;:18;;-1:-1:-1;;9755:18:0;:::i;:::-;;;;-1:-1:-1;;9784:7:0;:16;;;;;;;;;;;:21;;-1:-1:-1;;;;;;9784:21:0;-1:-1:-1;;;;;9784:21:0;;;;;;;;9823:33;;9784:16;;:7;9823:33;;9784:7;;9823:33;9482:382;;:::o;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:186::-;251:6;304:2;292:9;283:7;279:23;275:32;272:52;;;320:1;317;310:12;272:52;343:29;362:9;343:29;:::i;383:260::-;451:6;459;512:2;500:9;491:7;487:23;483:32;480:52;;;528:1;525;518:12;480:52;551:29;570:9;551:29;:::i;:::-;541:39;;599:38;633:2;622:9;618:18;599:38;:::i;:::-;589:48;;383:260;;;;;:::o;648:328::-;725:6;733;741;794:2;782:9;773:7;769:23;765:32;762:52;;;810:1;807;800:12;762:52;833:29;852:9;833:29;:::i;:::-;823:39;;881:38;915:2;904:9;900:18;881:38;:::i;:::-;871:48;;966:2;955:9;951:18;938:32;928:42;;648:328;;;;;:::o;981:1138::-;1076:6;1084;1092;1100;1153:3;1141:9;1132:7;1128:23;1124:33;1121:53;;;1170:1;1167;1160:12;1121:53;1193:29;1212:9;1193:29;:::i;:::-;1183:39;;1241:38;1275:2;1264:9;1260:18;1241:38;:::i;:::-;1231:48;;1326:2;1315:9;1311:18;1298:32;1288:42;;1381:2;1370:9;1366:18;1353:32;1404:18;1445:2;1437:6;1434:14;1431:34;;;1461:1;1458;1451:12;1431:34;1499:6;1488:9;1484:22;1474:32;;1544:7;1537:4;1533:2;1529:13;1525:27;1515:55;;1566:1;1563;1556:12;1515:55;1602:2;1589:16;1624:2;1620;1617:10;1614:36;;;1630:18;;:::i;:::-;1705:2;1699:9;1673:2;1759:13;;-1:-1:-1;;1755:22:1;;;1779:2;1751:31;1747:40;1735:53;;;1803:18;;;1823:22;;;1800:46;1797:72;;;1849:18;;:::i;:::-;1889:10;1885:2;1878:22;1924:2;1916:6;1909:18;1964:7;1959:2;1954;1950;1946:11;1942:20;1939:33;1936:53;;;1985:1;1982;1975:12;1936:53;2041:2;2036;2032;2028:11;2023:2;2015:6;2011:15;1998:46;2086:1;2081:2;2076;2068:6;2064:15;2060:24;2053:35;2107:6;2097:16;;;;;;;981:1138;;;;;;;:::o;2124:347::-;2189:6;2197;2250:2;2238:9;2229:7;2225:23;2221:32;2218:52;;;2266:1;2263;2256:12;2218:52;2289:29;2308:9;2289:29;:::i;:::-;2279:39;;2368:2;2357:9;2353:18;2340:32;2415:5;2408:13;2401:21;2394:5;2391:32;2381:60;;2437:1;2434;2427:12;2381:60;2460:5;2450:15;;;2124:347;;;;;:::o;2476:254::-;2544:6;2552;2605:2;2593:9;2584:7;2580:23;2576:32;2573:52;;;2621:1;2618;2611:12;2573:52;2644:29;2663:9;2644:29;:::i;:::-;2634:39;2720:2;2705:18;;;;2692:32;;-1:-1:-1;;;2476:254:1:o;2735:245::-;2793:6;2846:2;2834:9;2825:7;2821:23;2817:32;2814:52;;;2862:1;2859;2852:12;2814:52;2901:9;2888:23;2920:30;2944:5;2920:30;:::i;2985:249::-;3054:6;3107:2;3095:9;3086:7;3082:23;3078:32;3075:52;;;3123:1;3120;3113:12;3075:52;3155:9;3149:16;3174:30;3198:5;3174:30;:::i;3239:180::-;3298:6;3351:2;3339:9;3330:7;3326:23;3322:32;3319:52;;;3367:1;3364;3357:12;3319:52;-1:-1:-1;3390:23:1;;3239:180;-1:-1:-1;3239:180:1:o;3424:471::-;3465:3;3503:5;3497:12;3530:6;3525:3;3518:19;3555:1;3565:162;3579:6;3576:1;3573:13;3565:162;;;3641:4;3697:13;;;3693:22;;3687:29;3669:11;;;3665:20;;3658:59;3594:12;3565:162;;;3745:6;3742:1;3739:13;3736:87;;;3811:1;3804:4;3795:6;3790:3;3786:16;3782:27;3775:38;3736:87;-1:-1:-1;3877:2:1;3856:15;-1:-1:-1;;3852:29:1;3843:39;;;;3884:4;3839:50;;3424:471;-1:-1:-1;;3424:471:1:o;4108:488::-;-1:-1:-1;;;;;4377:15:1;;;4359:34;;4429:15;;4424:2;4409:18;;4402:43;4476:2;4461:18;;4454:34;;;4524:3;4519:2;4504:18;;4497:31;;;-1:-1:-1;;4545:45:1;;4570:19;;4562:6;4545:45;:::i;:::-;4537:53;4108:488;-1:-1:-1;;;;;;4108:488:1:o;4793:219::-;4942:2;4931:9;4924:21;4905:4;4962:44;5002:2;4991:9;4987:18;4979:6;4962:44;:::i;5429:414::-;5631:2;5613:21;;;5670:2;5650:18;;;5643:30;5709:34;5704:2;5689:18;;5682:62;-1:-1:-1;;;5775:2:1;5760:18;;5753:48;5833:3;5818:19;;5429:414::o;10209:413::-;10411:2;10393:21;;;10450:2;10430:18;;;10423:30;10489:34;10484:2;10469:18;;10462:62;-1:-1:-1;;;10555:2:1;10540:18;;10533:47;10612:3;10597:19;;10209:413::o;11222:128::-;11262:3;11293:1;11289:6;11286:1;11283:13;11280:39;;;11299:18;;:::i;:::-;-1:-1:-1;11335:9:1;;11222:128::o;11355:125::-;11395:4;11423:1;11420;11417:8;11414:34;;;11428:18;;:::i;:::-;-1:-1:-1;11465:9:1;;11355:125::o;11485:127::-;11546:10;11541:3;11537:20;11534:1;11527:31;11577:4;11574:1;11567:15;11601:4;11598:1;11591:15;11617:127;11678:10;11673:3;11669:20;11666:1;11659:31;11709:4;11706:1;11699:15;11733:4;11730:1;11723:15;11749:127;11810:10;11805:3;11801:20;11798:1;11791:31;11841:4;11838:1;11831:15;11865:4;11862:1;11855:15;11881:127;11942:10;11937:3;11933:20;11930:1;11923:31;11973:4;11970:1;11963:15;11997:4;11994:1;11987:15;12013:131;-1:-1:-1;;;;;;12087:32:1;;12077:43;;12067:71;;12134:1;12131;12124:12;12067:71;12013:131;:::o

Swarm Source

ipfs://377eb001f223e1fcaa8a9f3f493f41c06118872dfc6c2f891c73471e4b2c7fac
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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