creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/interfaces/IERC5267.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.0;\n\ninterface IERC5267 {\n    /**\n     * @dev MAY be emitted to signal that the domain could have changed.\n     */\n    event EIP712DomainChanged();\n\n    /**\n     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n     * signature.\n     */\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/cryptography/EIP712.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n    using Counters for Counters.Counter;\n\n    mapping(address => Counters.Counter) private _nonces;\n\n    // solhint-disable-next-line var-name-mixedcase\n    bytes32 private constant _PERMIT_TYPEHASH =\n        keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n    /**\n     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n     * However, to ensure consistency with the upgradeable transpiler, we will continue\n     * to reserve a slot.\n     * @custom:oz-renamed-from _PERMIT_TYPEHASH\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\n\n    /**\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n     *\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n     */\n    constructor(string memory name) EIP712(name, \"1\") {}\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public virtual override {\n        require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n\n        address signer = ECDSA.recover(hash, v, r, s);\n        require(signer == owner, \"ERC20Permit: invalid signature\");\n\n        _approve(owner, spender, value);\n    }\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    function nonces(address owner) public view virtual override returns (uint256) {\n        return _nonces[owner].current();\n    }\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @dev \"Consume a nonce\": return the current value and increment.\n     *\n     * _Available since v4.1._\n     */\n    function _useNonce(address owner) internal virtual returns (uint256 current) {\n        Counters.Counter storage nonce = _nonces[owner];\n        current = nonce.current();\n        nonce.increment();\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Counters.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n    struct Counter {\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\n        uint256 _value; // default: 0\n    }\n\n    function current(Counter storage counter) internal view returns (uint256) {\n        return counter._value;\n    }\n\n    function increment(Counter storage counter) internal {\n        unchecked {\n            counter._value += 1;\n        }\n    }\n\n    function decrement(Counter storage counter) internal {\n        uint256 value = counter._value;\n        require(value > 0, \"Counter: decrement overflow\");\n        unchecked {\n            counter._value = value - 1;\n        }\n    }\n\n    function reset(Counter storage counter) internal {\n        counter._value = 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n            mstore(0x1c, hash)\n            message := keccak256(0x00, 0x3c)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, \"\\x19\\x01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            data := keccak256(ptr, 0x42)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Data with intended validator, created from a\n     * `validator` and `data` according to the version 0 of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/cryptography/EIP712.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./ECDSA.sol\";\nimport \"../ShortStrings.sol\";\nimport \"../../interfaces/IERC5267.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n *\n * _Available since v3.4._\n *\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n */\nabstract contract EIP712 is IERC5267 {\n    using ShortStrings for *;\n\n    bytes32 private constant _TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n    // invalidate the cached domain separator if the chain id changes.\n    bytes32 private immutable _cachedDomainSeparator;\n    uint256 private immutable _cachedChainId;\n    address private immutable _cachedThis;\n\n    bytes32 private immutable _hashedName;\n    bytes32 private immutable _hashedVersion;\n\n    ShortString private immutable _name;\n    ShortString private immutable _version;\n    string private _nameFallback;\n    string private _versionFallback;\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    constructor(string memory name, string memory version) {\n        _name = name.toShortStringWithFallback(_nameFallback);\n        _version = version.toShortStringWithFallback(_versionFallback);\n        _hashedName = keccak256(bytes(name));\n        _hashedVersion = keccak256(bytes(version));\n\n        _cachedChainId = block.chainid;\n        _cachedDomainSeparator = _buildDomainSeparator();\n        _cachedThis = address(this);\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\n            return _cachedDomainSeparator;\n        } else {\n            return _buildDomainSeparator();\n        }\n    }\n\n    function _buildDomainSeparator() private view returns (bytes32) {\n        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n\n    /**\n     * @dev See {EIP-5267}.\n     *\n     * _Available since v4.9._\n     */\n    function eip712Domain()\n        public\n        view\n        virtual\n        override\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        )\n    {\n        return (\n            hex\"0f\", // 01111\n            _name.toStringWithFallback(_nameFallback),\n            _version.toStringWithFallback(_versionFallback),\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/ShortStrings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)\n\npragma solidity ^0.8.8;\n\nimport \"./StorageSlot.sol\";\n\n// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |\n// | length  | 0x                                                              BB |\ntype ShortString is bytes32;\n\n/**\n * @dev This library provides functions to convert short memory strings\n * into a `ShortString` type that can be used as an immutable variable.\n *\n * Strings of arbitrary length can be optimized using this library if\n * they are short enough (up to 31 bytes) by packing them with their\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\n * fallback mechanism can be used for every other case.\n *\n * Usage example:\n *\n * ```solidity\n * contract Named {\n *     using ShortStrings for *;\n *\n *     ShortString private immutable _name;\n *     string private _nameFallback;\n *\n *     constructor(string memory contractName) {\n *         _name = contractName.toShortStringWithFallback(_nameFallback);\n *     }\n *\n *     function name() external view returns (string memory) {\n *         return _name.toStringWithFallback(_nameFallback);\n *     }\n * }\n * ```\n */\nlibrary ShortStrings {\n    // Used as an identifier for strings longer than 31 bytes.\n    bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\n\n    error StringTooLong(string str);\n    error InvalidShortString();\n\n    /**\n     * @dev Encode a string of at most 31 chars into a `ShortString`.\n     *\n     * This will trigger a `StringTooLong` error is the input string is too long.\n     */\n    function toShortString(string memory str) internal pure returns (ShortString) {\n        bytes memory bstr = bytes(str);\n        if (bstr.length > 31) {\n            revert StringTooLong(str);\n        }\n        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\n    }\n\n    /**\n     * @dev Decode a `ShortString` back to a \"normal\" string.\n     */\n    function toString(ShortString sstr) internal pure returns (string memory) {\n        uint256 len = byteLength(sstr);\n        // using `new string(len)` would work locally but is not memory safe.\n        string memory str = new string(32);\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(str, len)\n            mstore(add(str, 0x20), sstr)\n        }\n        return str;\n    }\n\n    /**\n     * @dev Return the length of a `ShortString`.\n     */\n    function byteLength(ShortString sstr) internal pure returns (uint256) {\n        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\n        if (result > 31) {\n            revert InvalidShortString();\n        }\n        return result;\n    }\n\n    /**\n     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\n     */\n    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\n        if (bytes(value).length < 32) {\n            return toShortString(value);\n        } else {\n            StorageSlot.getStringSlot(store).value = value;\n            return ShortString.wrap(_FALLBACK_SENTINEL);\n        }\n    }\n\n    /**\n     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n     */\n    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\n        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n            return toString(value);\n        } else {\n            return store;\n        }\n    }\n\n    /**\n     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.\n     *\n     * WARNING: This will return the \"byte length\" of the string. This may not reflect the actual length in terms of\n     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\n     */\n    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\n        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {\n            return byteLength(value);\n        } else {\n            return bytes(store).length;\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n    uint8 internal constant RESOLUTION = 96;\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\n"
      },
      "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Immutable state\n/// @notice Functions that return immutable state of the router\ninterface IPeripheryImmutableState {\n    /// @return Returns the address of the Uniswap V3 factory\n    function factory() external view returns (address);\n\n    /// @return Returns the address of WETH9\n    function WETH9() external view returns (address);\n}\n"
      },
      "contracts/DecentralizedIndex.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol';\nimport './interfaces/ICamelotRouter.sol';\nimport './interfaces/IDecentralizedIndex.sol';\nimport './interfaces/IDexAdapter.sol';\nimport './interfaces/IFlashLoanRecipient.sol';\nimport './interfaces/IProtocolFeeRouter.sol';\nimport './interfaces/IRewardsWhitelister.sol';\nimport './interfaces/ITokenRewards.sol';\nimport './interfaces/IUniswapV2Router02.sol';\nimport './StakingPoolToken.sol';\n\nabstract contract DecentralizedIndex is\n  IDecentralizedIndex,\n  ERC20,\n  ERC20Permit\n{\n  using SafeERC20 for IERC20;\n\n  uint16 constant DEN = 10000;\n  uint8 constant SWAP_DELAY = 20; // seconds\n  address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n  IProtocolFeeRouter constant PROTOCOL_FEE_ROUTER =\n    IProtocolFeeRouter(0x7d544DD34ABbE24C8832db27820Ff53C151e949b);\n  IRewardsWhitelister constant REWARDS_WHITELIST =\n    IRewardsWhitelister(0xEc0Eb48d2D638f241c1a7F109e38ef2901E9450F);\n  IV3TwapUtilities constant V3_TWAP_UTILS =\n    IV3TwapUtilities(0x024ff47D552cB222b265D68C7aeB26E586D5229D);\n\n  uint256 public immutable override FLASH_FEE_AMOUNT_DAI; // 10 DAI\n  address public immutable override PAIRED_LP_TOKEN;\n  IDexAdapter public immutable DEX_HANDLER;\n  address immutable V2_ROUTER;\n  address immutable V3_ROUTER;\n  address immutable WETH;\n  address V2_POOL;\n\n  IndexType public immutable override indexType;\n  uint256 public immutable override created;\n  address public immutable override lpRewardsToken;\n  address public override lpStakingPool;\n\n  Config public config;\n  Fees public fees;\n  IndexAssetInfo[] public indexTokens;\n  mapping(address => bool) _isTokenInIndex;\n  mapping(address => uint8) _fundTokenIdx;\n  mapping(address => bool) _blacklist;\n\n  uint64 _partnerFirstWrapped;\n\n  uint64 _lastSwap;\n  uint8 _swapping;\n  uint8 _swapAndFeeOn = 1;\n  uint8 _unlocked = 1;\n  bool _initialized;\n\n  event FlashLoan(\n    address indexed executor,\n    address indexed recipient,\n    address token,\n    uint256 amount\n  );\n\n  modifier lock() {\n    require(_unlocked == 1, 'L');\n    _unlocked = 0;\n    _;\n    _unlocked = 1;\n  }\n\n  modifier onlyPartner() {\n    require(_msgSender() == config.partner, 'P');\n    _;\n  }\n\n  modifier noSwapOrFee() {\n    _swapAndFeeOn = 0;\n    _;\n    _swapAndFeeOn = 1;\n  }\n\n  constructor(\n    string memory _name,\n    string memory _symbol,\n    IndexType _idxType,\n    Config memory _config,\n    Fees memory _fees,\n    address _pairedLpToken,\n    address _lpRewardsToken,\n    address _dexHandler,\n    bool _stakeRestriction\n  ) ERC20(_name, _symbol) ERC20Permit(_name) {\n    require(_fees.buy <= (uint256(DEN) * 20) / 100);\n    require(_fees.sell <= (uint256(DEN) * 20) / 100);\n    require(_fees.burn <= (uint256(DEN) * 70) / 100);\n    require(_fees.bond <= (uint256(DEN) * 99) / 100);\n    require(_fees.debond <= (uint256(DEN) * 99) / 100);\n    require(_fees.partner <= (uint256(DEN) * 5) / 100);\n\n    indexType = _idxType;\n    created = block.timestamp;\n    fees = _fees;\n    config = _config;\n    lpRewardsToken = _lpRewardsToken;\n    DEX_HANDLER = IDexAdapter(_dexHandler);\n    address _v2Router = DEX_HANDLER.V2_ROUTER();\n    V2_ROUTER = _v2Router;\n    V3_ROUTER = DEX_HANDLER.V3_ROUTER();\n    address _finalPairedLpToken = _pairedLpToken == address(0)\n      ? DAI\n      : _pairedLpToken;\n    PAIRED_LP_TOKEN = _finalPairedLpToken;\n    FLASH_FEE_AMOUNT_DAI = 10 * 10 ** IERC20Metadata(DAI).decimals(); // 10 DAI\n    lpStakingPool = address(\n      new StakingPoolToken(\n        string.concat('Staked ', _name),\n        string.concat('s', _symbol),\n        _finalPairedLpToken,\n        lpRewardsToken,\n        _stakeRestriction ? _msgSender() : address(0),\n        PROTOCOL_FEE_ROUTER,\n        REWARDS_WHITELIST,\n        DEX_HANDLER,\n        V3_TWAP_UTILS\n      )\n    );\n    if (!DEX_HANDLER.ASYNC_INITIALIZE()) {\n      _initialize();\n    }\n    WETH = IUniswapV2Router02(_v2Router).WETH();\n    emit Create(address(this), _msgSender());\n  }\n\n  function initialize() external {\n    _initialize();\n  }\n\n  function _initialize() internal {\n    require(!_initialized, 'O');\n    _initialized = true;\n    address _v2Pool = DEX_HANDLER.getV2Pool(address(this), PAIRED_LP_TOKEN);\n    if (_v2Pool == address(0)) {\n      _v2Pool = DEX_HANDLER.createV2Pool(address(this), PAIRED_LP_TOKEN);\n    }\n    StakingPoolToken(lpStakingPool).setStakingToken(_v2Pool);\n    StakingPoolToken(lpStakingPool).renounceOwnership();\n    V2_POOL = _v2Pool;\n    emit Initialize(_msgSender(), _v2Pool);\n  }\n\n  function _transfer(\n    address _from,\n    address _to,\n    uint256 _amount\n  ) internal virtual override {\n    require(!_blacklist[_to], 'BK');\n    bool _buy = _from == V2_POOL && _to != V2_ROUTER;\n    bool _sell = _to == V2_POOL;\n    uint256 _fee;\n    if (_swapping == 0 && _swapAndFeeOn == 1) {\n      if (_from != V2_POOL) {\n        _processPreSwapFeesAndSwap();\n      }\n      if (_buy && fees.buy > 0) {\n        _fee = (_amount * fees.buy) / DEN;\n        super._transfer(_from, address(this), _fee);\n      }\n      if (_sell && fees.sell > 0) {\n        _fee = (_amount * fees.sell) / DEN;\n        super._transfer(_from, address(this), _fee);\n      }\n      if (!_buy && !_sell && config.hasTransferTax) {\n        _fee = _amount / 10000; // 0.01%\n        _fee = _fee == 0 && _amount > 0 ? 1 : _fee;\n        super._transfer(_from, address(this), _fee);\n      }\n    }\n    _processBurnFee(_fee);\n    super._transfer(_from, _to, _amount - _fee);\n  }\n\n  function _processPreSwapFeesAndSwap() internal {\n    bool _passesSwapDelay = block.timestamp > _lastSwap + SWAP_DELAY;\n    if (!_passesSwapDelay) {\n      return;\n    }\n    uint256 _bal = balanceOf(address(this));\n    if (_bal == 0) {\n      return;\n    }\n    uint256 _lpBal = balanceOf(V2_POOL);\n    uint256 _min = block.chainid == 1 ? _lpBal / 1000 : _lpBal / 4000; // 0.1%/0.025% LP bal\n    uint256 _max = _lpBal / 100; // 1%\n    if (_bal >= _min && _lpBal > 0) {\n      _swapping = 1;\n      _lastSwap = uint64(block.timestamp);\n      uint256 _totalAmt = _bal > _max ? _max : _bal;\n      uint256 _partnerAmt;\n      if (\n        fees.partner > 0 &&\n        config.partner != address(0) &&\n        !_blacklist[config.partner]\n      ) {\n        _partnerAmt = (_totalAmt * fees.partner) / DEN;\n        super._transfer(address(this), config.partner, _partnerAmt);\n      }\n      _feeSwap(_totalAmt - _partnerAmt);\n      _swapping = 0;\n    }\n  }\n\n  function _processBurnFee(uint256 _amtToProcess) internal {\n    if (_amtToProcess == 0 || fees.burn == 0) {\n      return;\n    }\n    _burn(address(this), (_amtToProcess * fees.burn) / DEN);\n  }\n\n  function _feeSwap(uint256 _amount) internal {\n    _approve(address(this), address(DEX_HANDLER), _amount);\n    address _rewards = StakingPoolToken(lpStakingPool).poolRewards();\n    uint256 _pairedLpBalBefore = IERC20(PAIRED_LP_TOKEN).balanceOf(_rewards);\n    DEX_HANDLER.swapV2Single(\n      address(this),\n      PAIRED_LP_TOKEN,\n      _amount,\n      0,\n      _rewards\n    );\n\n    if (PAIRED_LP_TOKEN == lpRewardsToken) {\n      uint256 _newPairedLpTkns = IERC20(PAIRED_LP_TOKEN).balanceOf(_rewards) -\n        _pairedLpBalBefore;\n      if (_newPairedLpTkns > 0) {\n        ITokenRewards(_rewards).depositRewardsNoTransfer(\n          PAIRED_LP_TOKEN,\n          _newPairedLpTkns\n        );\n      }\n    } else if (IERC20(PAIRED_LP_TOKEN).balanceOf(_rewards) > 0) {\n      ITokenRewards(_rewards).depositFromPairedLpToken(0, 0);\n    }\n  }\n\n  function _transferFromAndValidate(\n    IERC20 _token,\n    address _sender,\n    uint256 _amount\n  ) internal {\n    uint256 _balanceBefore = _token.balanceOf(address(this));\n    _token.safeTransferFrom(_sender, address(this), _amount);\n    require(_token.balanceOf(address(this)) >= _balanceBefore + _amount, 'TV');\n  }\n\n  function _bond() internal {\n    require(_initialized, 'I');\n    if (_partnerFirstWrapped == 0 && _msgSender() == config.partner) {\n      _partnerFirstWrapped = uint64(block.timestamp);\n    }\n  }\n\n  function _canWrapFeeFree(address _wrapper) internal view returns (bool) {\n    return\n      _isFirstIn() ||\n      (_wrapper == config.partner &&\n        _partnerFirstWrapped == 0 &&\n        block.timestamp <= created + 7 days);\n  }\n\n  function _isFirstIn() internal view returns (bool) {\n    return totalSupply() == 0;\n  }\n\n  function _isLastOut(uint256 _debondAmount) internal view returns (bool) {\n    return _debondAmount >= (totalSupply() * 98) / 100;\n  }\n\n  function processPreSwapFeesAndSwap() external override {\n    require(_msgSender() == StakingPoolToken(lpStakingPool).poolRewards(), 'R');\n    _processPreSwapFeesAndSwap();\n  }\n\n  function partner() external view override returns (address) {\n    return config.partner;\n  }\n\n  function BOND_FEE() external view override returns (uint16) {\n    return fees.bond;\n  }\n\n  function DEBOND_FEE() external view override returns (uint16) {\n    return fees.debond;\n  }\n\n  function isAsset(address _token) public view override returns (bool) {\n    return _isTokenInIndex[_token];\n  }\n\n  function getAllAssets()\n    external\n    view\n    override\n    returns (IndexAssetInfo[] memory)\n  {\n    return indexTokens;\n  }\n\n  function burn(uint256 _amount) external lock {\n    _burn(_msgSender(), _amount);\n  }\n\n  function manualProcessFee(uint256 _slip) external {\n    _transfer(address(this), address(this), 0);\n    address _rewards = StakingPoolToken(lpStakingPool).poolRewards();\n    ITokenRewards(_rewards).depositFromPairedLpToken(\n      0,\n      _slip > 50 ? 50 : _slip // 5% max\n    );\n  }\n\n  function addLiquidityV2(\n    uint256 _idxLPTokens,\n    uint256 _pairedLPTokens,\n    uint256 _slippage, // 100 == 10%, 1000 == 100%\n    uint256 _deadline\n  ) external override lock noSwapOrFee returns (uint256) {\n    uint256 _idxTokensBefore = balanceOf(address(this));\n    uint256 _pairedBefore = IERC20(PAIRED_LP_TOKEN).balanceOf(address(this));\n\n    super._transfer(_msgSender(), address(this), _idxLPTokens);\n    _approve(address(this), V2_ROUTER, _idxLPTokens);\n\n    IERC20(PAIRED_LP_TOKEN).safeTransferFrom(\n      _msgSender(),\n      address(this),\n      _pairedLPTokens\n    );\n    IERC20(PAIRED_LP_TOKEN).safeIncreaseAllowance(V2_ROUTER, _pairedLPTokens);\n\n    (, , uint256 _liquidity) = IUniswapV2Router02(V2_ROUTER).addLiquidity(\n      address(this),\n      PAIRED_LP_TOKEN,\n      _idxLPTokens,\n      _pairedLPTokens,\n      (_idxLPTokens * (1000 - _slippage)) / 1000,\n      (_pairedLPTokens * (1000 - _slippage)) / 1000,\n      _msgSender(),\n      _deadline\n    );\n    IERC20(PAIRED_LP_TOKEN).safeApprove(V2_ROUTER, 0);\n\n    // check & refund excess tokens from LPing\n    if (balanceOf(address(this)) > _idxTokensBefore) {\n      super._transfer(\n        address(this),\n        _msgSender(),\n        balanceOf(address(this)) - _idxTokensBefore\n      );\n    }\n    if (IERC20(PAIRED_LP_TOKEN).balanceOf(address(this)) > _pairedBefore) {\n      IERC20(PAIRED_LP_TOKEN).safeTransfer(\n        _msgSender(),\n        IERC20(PAIRED_LP_TOKEN).balanceOf(address(this)) - _pairedBefore\n      );\n    }\n    emit AddLiquidity(_msgSender(), _idxLPTokens, _pairedLPTokens);\n    return _liquidity;\n  }\n\n  function removeLiquidityV2(\n    uint256 _lpTokens,\n    uint256 _minIdxTokens, // 0 == 100% slippage\n    uint256 _minPairedLpToken, // 0 == 100% slippage\n    uint256 _deadline\n  ) external override lock noSwapOrFee {\n    _lpTokens = _lpTokens == 0\n      ? IERC20(V2_POOL).balanceOf(_msgSender())\n      : _lpTokens;\n    require(_lpTokens > 0, 'LT');\n\n    IERC20(V2_POOL).safeTransferFrom(_msgSender(), address(this), _lpTokens);\n    IERC20(V2_POOL).safeIncreaseAllowance(V2_ROUTER, _lpTokens);\n    IUniswapV2Router02(V2_ROUTER).removeLiquidity(\n      address(this),\n      PAIRED_LP_TOKEN,\n      _lpTokens,\n      _minIdxTokens,\n      _minPairedLpToken,\n      _msgSender(),\n      _deadline\n    );\n    emit RemoveLiquidity(_msgSender(), _lpTokens);\n  }\n\n  function flash(\n    address _recipient,\n    address _token,\n    uint256 _amount,\n    bytes calldata _data\n  ) external override lock {\n    require(_isTokenInIndex[_token], 'X');\n    address _rewards = StakingPoolToken(lpStakingPool).poolRewards();\n    address _feeRecipient = lpRewardsToken == DAI\n      ? address(this)\n      : PAIRED_LP_TOKEN == DAI\n        ? _rewards\n        : Ownable(address(V3_TWAP_UTILS)).owner();\n    IERC20(DAI).safeTransferFrom(\n      _msgSender(),\n      _feeRecipient,\n      FLASH_FEE_AMOUNT_DAI\n    );\n    if (lpRewardsToken == DAI) {\n      IERC20(DAI).safeIncreaseAllowance(_rewards, FLASH_FEE_AMOUNT_DAI);\n      ITokenRewards(_rewards).depositRewards(DAI, FLASH_FEE_AMOUNT_DAI);\n    }\n    uint256 _balance = IERC20(_token).balanceOf(address(this));\n    IERC20(_token).safeTransfer(_recipient, _amount);\n    IFlashLoanRecipient(_recipient).callback(_data);\n    require(IERC20(_token).balanceOf(address(this)) >= _balance, 'FA');\n    emit FlashLoan(_msgSender(), _recipient, _token, _amount);\n  }\n\n  function setPartner(address _partner) external onlyPartner {\n    config.partner = _partner;\n    emit SetPartner(_msgSender(), _partner);\n  }\n\n  function setPartnerFee(uint16 _fee) external onlyPartner {\n    require(_fee < fees.partner, 'L');\n    fees.partner = _fee;\n    emit SetPartnerFee(_msgSender(), _fee);\n  }\n\n  function rescueERC20(address _token) external lock {\n    // cannot withdraw tokens/assets that belong to the index\n    require(!isAsset(_token) && _token != address(this), 'U');\n    IERC20(_token).safeTransfer(\n      Ownable(address(V3_TWAP_UTILS)).owner(),\n      IERC20(_token).balanceOf(address(this))\n    );\n  }\n\n  function rescueETH() external lock {\n    require(address(this).balance > 0, 'E');\n    (bool _sent, ) = Ownable(address(V3_TWAP_UTILS)).owner().call{\n      value: address(this).balance\n    }('');\n    require(_sent, 'S');\n  }\n}\n"
      },
      "contracts/interfaces/ICamelotRouter.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2;\n\ninterface ICamelotRouter {\n  function factory() external view returns (address);\n\n  function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n    uint amountIn,\n    uint amountOutMin,\n    address[] calldata path,\n    address to,\n    address referrer,\n    uint deadline\n  ) external;\n}\n"
      },
      "contracts/interfaces/IDecentralizedIndex.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ninterface IDecentralizedIndex is IERC20 {\n  enum IndexType {\n    WEIGHTED,\n    UNWEIGHTED\n  }\n\n  struct Config {\n    address partner;\n    bool hasTransferTax;\n    bool blacklistTKNpTKNPoolV2;\n  }\n\n  // all fees: 1 == 0.01%, 10 == 0.1%, 100 == 1%\n  struct Fees {\n    uint16 burn;\n    uint16 bond;\n    uint16 debond;\n    uint16 buy;\n    uint16 sell;\n    uint16 partner;\n  }\n\n  struct IndexAssetInfo {\n    address token;\n    uint256 weighting;\n    uint256 basePriceUSDX96;\n    address c1; // arbitrary contract/address field we can use for an index\n    uint256 q1; // arbitrary quantity/number field we can use for an index\n  }\n\n  event Create(address indexed newIdx, address indexed wallet);\n  event Initialize(address indexed wallet, address v2Pool);\n  event Bond(\n    address indexed wallet,\n    address indexed token,\n    uint256 amountTokensBonded,\n    uint256 amountTokensMinted\n  );\n  event Debond(address indexed wallet, uint256 amountDebonded);\n  event AddLiquidity(\n    address indexed wallet,\n    uint256 amountTokens,\n    uint256 amountDAI\n  );\n  event RemoveLiquidity(address indexed wallet, uint256 amountLiquidity);\n  event SetPartner(address indexed wallet, address newPartner);\n  event SetPartnerFee(address indexed wallet, uint16 newFee);\n\n  function BOND_FEE() external view returns (uint16);\n\n  function DEBOND_FEE() external view returns (uint16);\n\n  function FLASH_FEE_AMOUNT_DAI() external view returns (uint256);\n\n  function PAIRED_LP_TOKEN() external view returns (address);\n\n  function indexType() external view returns (IndexType);\n\n  function created() external view returns (uint256);\n\n  function lpStakingPool() external view returns (address);\n\n  function lpRewardsToken() external view returns (address);\n\n  function partner() external view returns (address);\n\n  function getIdxPriceUSDX96() external view returns (uint256, uint256);\n\n  function isAsset(address token) external view returns (bool);\n\n  function getAllAssets() external view returns (IndexAssetInfo[] memory);\n\n  function getInitialAmount(\n    address sToken,\n    uint256 sAmount,\n    address tToken\n  ) external view returns (uint256);\n\n  function getTokenPriceUSDX96(address token) external view returns (uint256);\n\n  function processPreSwapFeesAndSwap() external;\n\n  function bond(address token, uint256 amount, uint256 amountMintMin) external;\n\n  function debond(\n    uint256 amount,\n    address[] memory token,\n    uint8[] memory percentage\n  ) external;\n\n  function addLiquidityV2(\n    uint256 idxTokens,\n    uint256 daiTokens,\n    uint256 slippage,\n    uint256 deadline\n  ) external returns (uint256);\n\n  function removeLiquidityV2(\n    uint256 lpTokens,\n    uint256 minTokens,\n    uint256 minDAI,\n    uint256 deadline\n  ) external;\n\n  function flash(\n    address recipient,\n    address token,\n    uint256 amount,\n    bytes calldata data\n  ) external;\n}\n"
      },
      "contracts/interfaces/IDexAdapter.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IDexAdapter {\n  function ASYNC_INITIALIZE() external view returns (bool);\n\n  function V2_ROUTER() external view returns (address);\n\n  function V3_ROUTER() external view returns (address);\n\n  function getV3Pool(\n    address _token0,\n    address _token1,\n    uint24 _poolFee\n  ) external view returns (address _pool);\n\n  function getV2Pool(\n    address _token0,\n    address _token1\n  ) external view returns (address _pool);\n\n  function createV2Pool(\n    address _token0,\n    address _token1\n  ) external returns (address _pool);\n\n  function swapV2Single(\n    address _tokenIn,\n    address _tokenOut,\n    uint256 _amountIn,\n    uint256 _amountOutMin,\n    address _recipient\n  ) external returns (uint256 _amountOut);\n\n  function swapV3Single(\n    address _tokenIn,\n    address _tokenOut,\n    uint24 _fee,\n    uint256 _amountIn,\n    uint256 _amountOutMin,\n    address _recipient\n  ) external returns (uint256 _amountOut);\n\n  function addLiquidity(\n    address tokenA,\n    address tokenB,\n    uint256 amountADesired,\n    uint256 amountBDesired,\n    uint256 amountAMin,\n    uint256 amountBMin,\n    address to,\n    uint256 deadline\n  ) external;\n\n  function removeLiquidity(\n    address tokenA,\n    address tokenB,\n    uint256 liquidity,\n    uint256 amountAMin,\n    uint256 amountBMin,\n    address to,\n    uint256 deadline\n  ) external;\n}\n"
      },
      "contracts/interfaces/IFlashLoanRecipient.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IFlashLoanRecipient {\n  function callback(bytes calldata data) external;\n}\n"
      },
      "contracts/interfaces/IPEAS.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\ninterface IPEAS is IERC20 {\n  event Burn(address indexed user, uint256 amount);\n\n  function burn(uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/IProtocolFeeRouter.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport './IProtocolFees.sol';\n\ninterface IProtocolFeeRouter {\n  function protocolFees() external view returns (IProtocolFees);\n}\n"
      },
      "contracts/interfaces/IProtocolFees.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IProtocolFees {\n  event SetYieldAdmin(uint256 newFee);\n  event SetYieldBurn(uint256 newFee);\n\n  function DEN() external view returns (uint256);\n\n  function yieldAdmin() external view returns (uint256);\n\n  function yieldBurn() external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IRewardsWhitelister.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IRewardsWhitelister {\n  function whitelist(address token) external view returns (bool);\n\n  function getFullWhitelist() external view returns (address[] memory);\n}\n"
      },
      "contracts/interfaces/IStakingPoolToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IStakingPoolToken {\n  event Stake(address indexed executor, address indexed user, uint256 amount);\n\n  event Unstake(address indexed user, uint256 amount);\n\n  function indexFund() external view returns (address);\n\n  function stakingToken() external view returns (address);\n\n  function poolRewards() external view returns (address);\n\n  function stakeUserRestriction() external view returns (address);\n\n  function stake(address user, uint256 amount) external;\n\n  function unstake(uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/ITokenRewards.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface ITokenRewards {\n  event AddShares(address indexed wallet, uint256 amount);\n\n  event RemoveShares(address indexed wallet, uint256 amount);\n\n  event ClaimReward(address indexed wallet);\n\n  event DistributeReward(\n    address indexed wallet,\n    address indexed token,\n    uint256 amount\n  );\n\n  event DepositRewards(\n    address indexed wallet,\n    address indexed token,\n    uint256 amount\n  );\n\n  function totalShares() external view returns (uint256);\n\n  function totalStakers() external view returns (uint256);\n\n  function rewardsToken() external view returns (address);\n\n  function trackingToken() external view returns (address);\n\n  function depositFromPairedLpToken(\n    uint256 amount,\n    uint256 slippageOverride\n  ) external;\n\n  function depositRewards(address token, uint256 amount) external;\n\n  function depositRewardsNoTransfer(address token, uint256 amount) external;\n\n  function claimReward(address wallet) external;\n\n  function setShares(\n    address wallet,\n    uint256 amount,\n    bool sharesRemoving\n  ) external;\n}\n"
      },
      "contracts/interfaces/IUniswapV2Pair.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IUniswapV2Pair {\n  function token0() external view returns (address);\n\n  function token1() external view returns (address);\n\n  function getReserves()\n    external\n    view\n    returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n}\n"
      },
      "contracts/interfaces/IUniswapV2Router02.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IUniswapV2Router02 {\n  function factory() external view returns (address);\n\n  function WETH() external view returns (address);\n\n  function addLiquidity(\n    address tokenA,\n    address tokenB,\n    uint amountADesired,\n    uint amountBDesired,\n    uint amountAMin,\n    uint amountBMin,\n    address to,\n    uint deadline\n  ) external returns (uint amountA, uint amountB, uint liquidity);\n\n  function removeLiquidity(\n    address tokenA,\n    address tokenB,\n    uint liquidity,\n    uint amountAMin,\n    uint amountBMin,\n    address to,\n    uint deadline\n  ) external returns (uint amountA, uint amountB);\n\n  function swapETHForExactTokens(\n    uint256 amountOut,\n    address[] calldata path,\n    address to,\n    uint256 deadline\n  ) external payable returns (uint256[] memory amounts);\n\n  function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n    uint amountIn,\n    uint amountOutMin,\n    address[] calldata path,\n    address to,\n    uint deadline\n  ) external;\n}\n"
      },
      "contracts/interfaces/IV3TwapUtilities.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IV3TwapUtilities {\n  function getV3Pool(\n    address v3Factory,\n    address token0,\n    address token1\n  ) external view returns (address);\n\n  function getV3Pool(\n    address v3Factory,\n    address token0,\n    address token1,\n    uint24 poolFee\n  ) external view returns (address);\n\n  function getV3Pool(\n    address v3Factory,\n    address token0,\n    address token1,\n    int24 tickSpacing\n  ) external view returns (address);\n\n  function getPoolPriceUSDX96(\n    address pricePool,\n    address nativeStablePool,\n    address WETH9\n  ) external view returns (uint256);\n\n  function sqrtPriceX96FromPoolAndInterval(\n    address pool\n  ) external view returns (uint160);\n\n  function priceX96FromSqrtPriceX96(\n    uint160 sqrtPriceX96\n  ) external pure returns (uint256);\n}\n"
      },
      "contracts/libraries/BokkyPooBahsDateTimeLibrary.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n// ----------------------------------------------------------------------------\n// BokkyPooBah's DateTime Library v1.00\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit      | Range         | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year      | 1970 ... 2345 |\n// month     | 1 ... 12      |\n// day       | 1 ... 31      |\n// hour      | 0 ... 23      |\n// minute    | 0 ... 59      |\n// second    | 0 ... 59      |\n// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018.\n//\n// GNU Lesser General Public License 3.0\n// https://www.gnu.org/licenses/lgpl-3.0.en.html\n// ----------------------------------------------------------------------------\n\nlibrary BokkyPooBahsDateTimeLibrary {\n  uint constant SECONDS_PER_DAY = 24 * 60 * 60;\n  int constant OFFSET19700101 = 2440588;\n\n  // ------------------------------------------------------------------------\n  // Calculate year/month/day from the number of days since 1970/01/01 using\n  // the date conversion algorithm from\n  //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n  // and adding the offset 2440588 so that 1970/01/01 is day 0\n  //\n  // int L = days + 68569 + offset\n  // int N = 4 * L / 146097\n  // L = L - (146097 * N + 3) / 4\n  // year = 4000 * (L + 1) / 1461001\n  // L = L - 1461 * year / 4 + 31\n  // month = 80 * L / 2447\n  // dd = L - 2447 * month / 80\n  // L = month / 11\n  // month = month + 2 - 12 * L\n  // year = 100 * (N - 49) + year + L\n  // ------------------------------------------------------------------------\n  function _daysToDate(\n    uint _days\n  ) internal pure returns (uint year, uint month, uint day) {\n    int __days = int(_days);\n\n    int L = __days + 68569 + OFFSET19700101;\n    int N = (4 * L) / 146097;\n    L = L - (146097 * N + 3) / 4;\n    int _year = (4000 * (L + 1)) / 1461001;\n    L = L - (1461 * _year) / 4 + 31;\n    int _month = (80 * L) / 2447;\n    int _day = L - (2447 * _month) / 80;\n    L = _month / 11;\n    _month = _month + 2 - 12 * L;\n    _year = 100 * (N - 49) + _year + L;\n\n    year = uint(_year);\n    month = uint(_month);\n    day = uint(_day);\n  }\n\n  function timestampToDate(\n    uint timestamp\n  ) internal pure returns (uint year, uint month, uint day) {\n    (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n  }\n}\n"
      },
      "contracts/StakingPoolToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './interfaces/IDexAdapter.sol';\nimport './interfaces/IRewardsWhitelister.sol';\nimport './interfaces/IProtocolFeeRouter.sol';\nimport './interfaces/IStakingPoolToken.sol';\nimport './TokenRewards.sol';\n\ncontract StakingPoolToken is IStakingPoolToken, ERC20, Ownable {\n  using SafeERC20 for IERC20;\n\n  address public immutable override indexFund;\n  address public immutable override poolRewards;\n  address public override stakeUserRestriction;\n  address public override stakingToken;\n\n  modifier onlyRestricted() {\n    require(_msgSender() == stakeUserRestriction, 'R');\n    _;\n  }\n\n  constructor(\n    string memory _name,\n    string memory _symbol,\n    address _pairedLpToken,\n    address _rewardsToken,\n    address _stakeUserRestriction,\n    IProtocolFeeRouter _feeRouter,\n    IRewardsWhitelister _rewardsWhitelist,\n    IDexAdapter _dexHandler,\n    IV3TwapUtilities _v3TwapUtilities\n  ) ERC20(_name, _symbol) {\n    indexFund = _msgSender();\n    stakeUserRestriction = _stakeUserRestriction;\n    poolRewards = address(\n      new TokenRewards(\n        _feeRouter,\n        _rewardsWhitelist,\n        _dexHandler,\n        _v3TwapUtilities,\n        indexFund,\n        _pairedLpToken,\n        address(this),\n        _rewardsToken\n      )\n    );\n  }\n\n  function stake(address _user, uint256 _amount) external override {\n    require(stakingToken != address(0), 'I');\n    if (stakeUserRestriction != address(0)) {\n      require(_user == stakeUserRestriction, 'U');\n    }\n    _mint(_user, _amount);\n    IERC20(stakingToken).safeTransferFrom(_msgSender(), address(this), _amount);\n    emit Stake(_msgSender(), _user, _amount);\n  }\n\n  function unstake(uint256 _amount) external override {\n    _burn(_msgSender(), _amount);\n    IERC20(stakingToken).safeTransfer(_msgSender(), _amount);\n    emit Unstake(_msgSender(), _amount);\n  }\n\n  function setStakingToken(address _stakingToken) external onlyOwner {\n    require(stakingToken == address(0), 'S');\n    stakingToken = _stakingToken;\n  }\n\n  function removeStakeUserRestriction() external onlyRestricted {\n    stakeUserRestriction = address(0);\n  }\n\n  function setStakeUserRestriction(address _user) external onlyRestricted {\n    stakeUserRestriction = _user;\n  }\n\n  function _afterTokenTransfer(\n    address _from,\n    address _to,\n    uint256 _amount\n  ) internal override {\n    if (_from != address(0) && _from != address(0xdead)) {\n      TokenRewards(poolRewards).setShares(_from, _amount, true);\n    }\n    if (_to != address(0) && _to != address(0xdead)) {\n      TokenRewards(poolRewards).setShares(_to, _amount, false);\n    }\n  }\n}\n"
      },
      "contracts/TokenRewards.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Context.sol';\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\nimport './interfaces/IDecentralizedIndex.sol';\nimport './interfaces/IDexAdapter.sol';\nimport './interfaces/IPEAS.sol';\nimport './interfaces/IRewardsWhitelister.sol';\nimport './interfaces/IProtocolFees.sol';\nimport './interfaces/IProtocolFeeRouter.sol';\nimport './interfaces/ITokenRewards.sol';\nimport './interfaces/IV3TwapUtilities.sol';\nimport './libraries/BokkyPooBahsDateTimeLibrary.sol';\n\ncontract TokenRewards is ITokenRewards, Context {\n  using SafeERC20 for IERC20;\n\n  uint256 constant PRECISION = 10 ** 36;\n  uint24 constant REWARDS_POOL_FEE = 10000; // 1%\n  address immutable INDEX_FUND;\n  address immutable PAIRED_LP_TOKEN;\n  IProtocolFeeRouter immutable PROTOCOL_FEE_ROUTER;\n  IRewardsWhitelister immutable REWARDS_WHITELISTER;\n  IDexAdapter immutable DEX_HANDLER;\n  IV3TwapUtilities immutable V3_TWAP_UTILS;\n\n  struct Reward {\n    uint256 excluded;\n    uint256 realized;\n  }\n\n  address public immutable override trackingToken;\n  address public immutable override rewardsToken; // main rewards token\n  uint256 public override totalShares;\n  uint256 public override totalStakers;\n  mapping(address => uint256) public shares;\n  // reward token => user => Reward\n  mapping(address => mapping(address => Reward)) public rewards;\n\n  uint256 _rewardsSwapSlippage = 20; // 2%\n  // reward token => amount\n  mapping(address => uint256) _rewardsPerShare;\n  // reward token => amount\n  mapping(address => uint256) public rewardsDistributed;\n  // reward token => amount\n  mapping(address => uint256) public rewardsDeposited;\n  // reward token => month => amount\n  mapping(address => mapping(uint256 => uint256)) public rewardsDepMonthly;\n  // all deposited rewards tokens\n  address[] _allRewardsTokens;\n  mapping(address => bool) _depositedRewardsToken;\n\n  constructor(\n    IProtocolFeeRouter _feeRouter,\n    IRewardsWhitelister _rewardsWhitelist,\n    IDexAdapter _dexHandler,\n    IV3TwapUtilities _v3TwapUtilities,\n    address _indexFund,\n    address _pairedLpToken,\n    address _trackingToken,\n    address _rewardsToken\n  ) {\n    PROTOCOL_FEE_ROUTER = _feeRouter;\n    REWARDS_WHITELISTER = _rewardsWhitelist;\n    DEX_HANDLER = _dexHandler;\n    V3_TWAP_UTILS = _v3TwapUtilities;\n    INDEX_FUND = _indexFund;\n    PAIRED_LP_TOKEN = _pairedLpToken;\n    trackingToken = _trackingToken;\n    rewardsToken = _rewardsToken;\n  }\n\n  function setShares(\n    address _wallet,\n    uint256 _amount,\n    bool _sharesRemoving\n  ) external override {\n    require(_msgSender() == trackingToken, 'UNAUTHORIZED');\n    _setShares(_wallet, _amount, _sharesRemoving);\n  }\n\n  function _setShares(\n    address _wallet,\n    uint256 _amount,\n    bool _sharesRemoving\n  ) internal {\n    _processFeesIfApplicable();\n    if (_sharesRemoving) {\n      _removeShares(_wallet, _amount);\n      emit RemoveShares(_wallet, _amount);\n    } else {\n      _addShares(_wallet, _amount);\n      emit AddShares(_wallet, _amount);\n    }\n  }\n\n  function _addShares(address _wallet, uint256 _amount) internal {\n    if (shares[_wallet] > 0) {\n      _distributeReward(_wallet);\n    }\n    uint256 sharesBefore = shares[_wallet];\n    totalShares += _amount;\n    shares[_wallet] += _amount;\n    if (sharesBefore == 0 && shares[_wallet] > 0) {\n      totalStakers++;\n    }\n    _resetExcluded(_wallet);\n  }\n\n  function _removeShares(address _wallet, uint256 _amount) internal {\n    require(shares[_wallet] > 0 && _amount <= shares[_wallet], 'RE');\n    _distributeReward(_wallet);\n    totalShares -= _amount;\n    shares[_wallet] -= _amount;\n    if (shares[_wallet] == 0) {\n      totalStakers--;\n    }\n    _resetExcluded(_wallet);\n  }\n\n  function _processFeesIfApplicable() internal {\n    IDecentralizedIndex(INDEX_FUND).processPreSwapFeesAndSwap();\n  }\n\n  function depositFromPairedLpToken(\n    uint256 _amountTknDepositing,\n    uint256 _slippageOverride\n  ) public override {\n    require(PAIRED_LP_TOKEN != rewardsToken, 'R');\n    require(_slippageOverride <= 200, 'MS'); // 20%\n    if (_amountTknDepositing > 0) {\n      IERC20(PAIRED_LP_TOKEN).safeTransferFrom(\n        _msgSender(),\n        address(this),\n        _amountTknDepositing\n      );\n    }\n    uint256 _amountTkn = IERC20(PAIRED_LP_TOKEN).balanceOf(address(this));\n    require(_amountTkn > 0, 'A');\n    uint256 _adminAmt = _getAdminFeeFromAmount(_amountTkn);\n    _amountTkn -= _adminAmt;\n    (address _token0, address _token1) = PAIRED_LP_TOKEN < rewardsToken\n      ? (PAIRED_LP_TOKEN, rewardsToken)\n      : (rewardsToken, PAIRED_LP_TOKEN);\n    address _pool = DEX_HANDLER.getV3Pool(_token0, _token1, REWARDS_POOL_FEE);\n    uint160 _rewardsSqrtPriceX96 = V3_TWAP_UTILS\n      .sqrtPriceX96FromPoolAndInterval(_pool);\n    uint256 _rewardsPriceX96 = V3_TWAP_UTILS.priceX96FromSqrtPriceX96(\n      _rewardsSqrtPriceX96\n    );\n    uint256 _amountOut = _token0 == PAIRED_LP_TOKEN\n      ? (_rewardsPriceX96 * _amountTkn) / FixedPoint96.Q96\n      : (_amountTkn * FixedPoint96.Q96) / _rewardsPriceX96;\n\n    uint256 _slippage = _slippageOverride > 0\n      ? _slippageOverride\n      : _rewardsSwapSlippage;\n    _swapForRewards(\n      _amountTkn,\n      _amountOut,\n      _slippage,\n      _slippageOverride > 0,\n      _adminAmt\n    );\n  }\n\n  function depositRewards(address _token, uint256 _amount) external override {\n    _depositRewardsFromToken(_msgSender(), _token, _amount, true);\n  }\n\n  function depositRewardsNoTransfer(\n    address _token,\n    uint256 _amount\n  ) external override {\n    require(_msgSender() == INDEX_FUND, 'AUTH');\n    _depositRewardsFromToken(_msgSender(), _token, _amount, false);\n  }\n\n  function _depositRewardsFromToken(\n    address _user,\n    address _token,\n    uint256 _amount,\n    bool _shouldTransfer\n  ) internal {\n    require(_amount > 0, 'A');\n    require(_isValidRewardsToken(_token), 'V');\n    uint256 _finalAmt = _amount;\n    if (_shouldTransfer) {\n      uint256 _balBefore = IERC20(_token).balanceOf(address(this));\n      IERC20(_token).safeTransferFrom(_user, address(this), _finalAmt);\n      _finalAmt = IERC20(_token).balanceOf(address(this)) - _balBefore;\n    }\n    uint256 _adminAmt = _getAdminFeeFromAmount(_finalAmt);\n    if (_adminAmt > 0) {\n      IERC20(_token).safeTransfer(\n        Ownable(address(V3_TWAP_UTILS)).owner(),\n        _adminAmt\n      );\n      _finalAmt -= _adminAmt;\n    }\n    _depositRewards(_token, _finalAmt);\n  }\n\n  function _depositRewards(address _token, uint256 _amountTotal) internal {\n    if (!_depositedRewardsToken[_token]) {\n      _depositedRewardsToken[_token] = true;\n      _allRewardsTokens.push(_token);\n    }\n    if (_amountTotal == 0) {\n      return;\n    }\n    if (totalShares == 0) {\n      require(_token == rewardsToken, 'R');\n      _burnRewards(_amountTotal);\n      return;\n    }\n\n    uint256 _depositAmount = _amountTotal;\n    if (_token == rewardsToken) {\n      (, uint256 _yieldBurnFee) = _getYieldFees();\n      if (_yieldBurnFee > 0) {\n        uint256 _burnAmount = (_amountTotal * _yieldBurnFee) /\n          PROTOCOL_FEE_ROUTER.protocolFees().DEN();\n        if (_burnAmount > 0) {\n          _burnRewards(_burnAmount);\n          _depositAmount -= _burnAmount;\n        }\n      }\n    }\n    rewardsDeposited[_token] += _depositAmount;\n    rewardsDepMonthly[_token][\n      beginningOfMonth(block.timestamp)\n    ] += _depositAmount;\n    _rewardsPerShare[_token] += (PRECISION * _depositAmount) / totalShares;\n    emit DepositRewards(_msgSender(), _token, _depositAmount);\n  }\n\n  function _distributeReward(address _wallet) internal {\n    if (shares[_wallet] == 0) {\n      return;\n    }\n    for (uint256 _i; _i < _allRewardsTokens.length; _i++) {\n      address _token = _allRewardsTokens[_i];\n      uint256 _amount = getUnpaid(_token, _wallet);\n      rewards[_token][_wallet].realized += _amount;\n      rewards[_token][_wallet].excluded = _cumulativeRewards(\n        _token,\n        shares[_wallet]\n      );\n      if (_amount > 0) {\n        rewardsDistributed[_token] += _amount;\n        IERC20(_token).safeTransfer(_wallet, _amount);\n        emit DistributeReward(_wallet, _token, _amount);\n      }\n    }\n  }\n\n  function _resetExcluded(address _wallet) internal {\n    for (uint256 _i; _i < _allRewardsTokens.length; _i++) {\n      address _token = _allRewardsTokens[_i];\n      rewards[_token][_wallet].excluded = _cumulativeRewards(\n        _token,\n        shares[_wallet]\n      );\n    }\n  }\n\n  function _burnRewards(uint256 _burnAmount) internal {\n    try IPEAS(rewardsToken).burn(_burnAmount) {} catch {\n      IERC20(rewardsToken).safeTransfer(address(0xdead), _burnAmount);\n    }\n  }\n\n  function _isValidRewardsToken(address _token) internal view returns (bool) {\n    return _token == rewardsToken || REWARDS_WHITELISTER.whitelist(_token);\n  }\n\n  function _getAdminFeeFromAmount(\n    uint256 _amount\n  ) internal view returns (uint256) {\n    (uint256 _yieldAdminFee, ) = _getYieldFees();\n    if (_yieldAdminFee == 0) {\n      return 0;\n    }\n    return\n      (_amount * _yieldAdminFee) / PROTOCOL_FEE_ROUTER.protocolFees().DEN();\n  }\n\n  function _getYieldFees()\n    internal\n    view\n    returns (uint256 _admin, uint256 _burn)\n  {\n    IProtocolFees _fees = PROTOCOL_FEE_ROUTER.protocolFees();\n    if (address(_fees) != address(0)) {\n      _admin = _fees.yieldAdmin();\n      _burn = _fees.yieldBurn();\n    }\n  }\n\n  function _swapForRewards(\n    uint256 _amountIn,\n    uint256 _amountOut,\n    uint256 _slippage,\n    bool _isSlipOverride,\n    uint256 _adminAmt\n  ) internal {\n    uint256 _balBefore = IERC20(rewardsToken).balanceOf(address(this));\n    IERC20(PAIRED_LP_TOKEN).safeIncreaseAllowance(\n      address(DEX_HANDLER),\n      _amountIn\n    );\n    try\n      DEX_HANDLER.swapV3Single(\n        PAIRED_LP_TOKEN,\n        rewardsToken,\n        REWARDS_POOL_FEE,\n        _amountIn,\n        (_amountOut * (1000 - _slippage)) / 1000,\n        address(this)\n      )\n    {\n      if (_adminAmt > 0) {\n        IERC20(PAIRED_LP_TOKEN).safeTransfer(\n          Ownable(address(V3_TWAP_UTILS)).owner(),\n          _adminAmt\n        );\n      }\n      _rewardsSwapSlippage = 20;\n      _depositRewards(\n        rewardsToken,\n        IERC20(rewardsToken).balanceOf(address(this)) - _balBefore\n      );\n    } catch {\n      if (!_isSlipOverride && _rewardsSwapSlippage < 200) {\n        _rewardsSwapSlippage += 10;\n      }\n      IERC20(PAIRED_LP_TOKEN).safeDecreaseAllowance(\n        address(DEX_HANDLER),\n        _amountIn\n      );\n    }\n  }\n\n  function beginningOfMonth(uint256 _timestamp) public pure returns (uint256) {\n    (, , uint256 _dayOfMonth) = BokkyPooBahsDateTimeLibrary.timestampToDate(\n      _timestamp\n    );\n    return _timestamp - ((_dayOfMonth - 1) * 1 days) - (_timestamp % 1 days);\n  }\n\n  function claimReward(address _wallet) external override {\n    _distributeReward(_wallet);\n    emit ClaimReward(_wallet);\n  }\n\n  function getUnpaid(\n    address _token,\n    address _wallet\n  ) public view returns (uint256) {\n    if (shares[_wallet] == 0) {\n      return 0;\n    }\n    uint256 earnedRewards = _cumulativeRewards(_token, shares[_wallet]);\n    uint256 rewardsExcluded = rewards[_token][_wallet].excluded;\n    if (earnedRewards <= rewardsExcluded) {\n      return 0;\n    }\n    return earnedRewards - rewardsExcluded;\n  }\n\n  function _cumulativeRewards(\n    address _token,\n    uint256 _share\n  ) internal view returns (uint256) {\n    return (_share * _rewardsPerShare[_token]) / PRECISION;\n  }\n}\n"
      },
      "contracts/WeightedIndex.sol": {
        "content": "// https://peapods.finance\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\nimport './interfaces/IUniswapV2Pair.sol';\nimport './interfaces/IV3TwapUtilities.sol';\nimport './DecentralizedIndex.sol';\n\ncontract WeightedIndex is DecentralizedIndex {\n  using SafeERC20 for IERC20;\n\n  uint256 _totalWeights;\n\n  constructor(\n    string memory _name,\n    string memory _symbol,\n    Config memory _config,\n    Fees memory _fees,\n    address[] memory _tokens,\n    uint256[] memory _weights,\n    address _pairedLpToken,\n    address _lpRewardsToken,\n    address _dexHandler,\n    bool _stakeRestriction\n  )\n    DecentralizedIndex(\n      _name,\n      _symbol,\n      IndexType.WEIGHTED,\n      _config,\n      _fees,\n      _pairedLpToken,\n      _lpRewardsToken,\n      _dexHandler,\n      _stakeRestriction\n    )\n  {\n    require(_tokens.length == _weights.length, 'V');\n    uint256 _tl = _tokens.length;\n    for (uint8 _i; _i < _tl; _i++) {\n      require(!_isTokenInIndex[_tokens[_i]], 'D');\n      require(_weights[_i] > 0, 'W');\n      indexTokens.push(\n        IndexAssetInfo({\n          token: _tokens[_i],\n          basePriceUSDX96: 0,\n          weighting: _weights[_i],\n          c1: address(0),\n          q1: 0 // amountsPerIdxTokenX96\n        })\n      );\n      _totalWeights += _weights[_i];\n      _fundTokenIdx[_tokens[_i]] = _i;\n      _isTokenInIndex[_tokens[_i]] = true;\n\n      if (_config.blacklistTKNpTKNPoolV2 && _tokens[_i] != _pairedLpToken) {\n        address _blkPool = IDexAdapter(_dexHandler).createV2Pool(\n          address(this),\n          _tokens[_i]\n        );\n        _blacklist[_blkPool] = true;\n      }\n    }\n    // at idx == 0, need to find X in [1/X = tokenWeightAtIdx/totalWeights]\n    // at idx > 0, need to find Y in (Y/X = tokenWeightAtIdx/totalWeights)\n    uint256 _xX96 = (FixedPoint96.Q96 * _totalWeights) / _weights[0];\n    for (uint256 _i; _i < _tl; _i++) {\n      indexTokens[_i].q1 =\n        (_weights[_i] * _xX96 * 10 ** IERC20Metadata(_tokens[_i]).decimals()) /\n        _totalWeights;\n    }\n  }\n\n  function _getNativePriceUSDX96() internal view returns (uint256) {\n    IUniswapV2Pair _nativeStablePool = IUniswapV2Pair(\n      DEX_HANDLER.getV2Pool(DAI, WETH)\n    );\n    address _token0 = _nativeStablePool.token0();\n    (uint8 _decimals0, uint8 _decimals1) = (\n      IERC20Metadata(_token0).decimals(),\n      IERC20Metadata(_nativeStablePool.token1()).decimals()\n    );\n    (uint112 _res0, uint112 _res1, ) = _nativeStablePool.getReserves();\n    return\n      _token0 == DAI\n        ? (FixedPoint96.Q96 * _res0 * 10 ** _decimals1) /\n          _res1 /\n          10 ** _decimals0\n        : (FixedPoint96.Q96 * _res1 * 10 ** _decimals0) /\n          _res0 /\n          10 ** _decimals1;\n  }\n\n  function _getTokenPriceUSDX96(\n    address _token\n  ) internal view returns (uint256) {\n    if (_token == WETH) {\n      return _getNativePriceUSDX96();\n    }\n    IUniswapV2Pair _pool = IUniswapV2Pair(DEX_HANDLER.getV2Pool(_token, WETH));\n    address _token0 = _pool.token0();\n    uint8 _decimals0 = IERC20Metadata(_token0).decimals();\n    uint8 _decimals1 = IERC20Metadata(_pool.token1()).decimals();\n    (uint112 _res0, uint112 _res1, ) = _pool.getReserves();\n    uint256 _nativePriceUSDX96 = _getNativePriceUSDX96();\n    return\n      _token0 == WETH\n        ? (_nativePriceUSDX96 * _res0 * 10 ** _decimals1) /\n          _res1 /\n          10 ** _decimals0\n        : (_nativePriceUSDX96 * _res1 * 10 ** _decimals0) /\n          _res0 /\n          10 ** _decimals1;\n  }\n\n  function bond(\n    address _token,\n    uint256 _amount,\n    uint256 _amountMintMin\n  ) external override lock noSwapOrFee {\n    require(_isTokenInIndex[_token], 'IT');\n    uint256 _tokenIdx = _fundTokenIdx[_token];\n    uint256 _tokenCurSupply = IERC20(_token).balanceOf(address(this));\n    bool _firstIn = _isFirstIn();\n    uint256 _tokenAmtSupplyRatioX96 = _firstIn\n      ? FixedPoint96.Q96\n      : (_amount * FixedPoint96.Q96) / _tokenCurSupply;\n    uint256 _tokensMinted;\n    if (_firstIn) {\n      _tokensMinted =\n        (_amount * FixedPoint96.Q96 * 10 ** decimals()) /\n        indexTokens[_tokenIdx].q1;\n    } else {\n      _tokensMinted =\n        (totalSupply() * _tokenAmtSupplyRatioX96) /\n        FixedPoint96.Q96;\n    }\n    uint256 _feeTokens = _canWrapFeeFree(_msgSender())\n      ? 0\n      : (_tokensMinted * fees.bond) / DEN;\n    require(_tokensMinted - _feeTokens >= _amountMintMin, 'M');\n    _mint(_msgSender(), _tokensMinted - _feeTokens);\n    if (_feeTokens > 0) {\n      _mint(address(this), _feeTokens);\n      _processBurnFee(_feeTokens);\n    }\n    uint256 _il = indexTokens.length;\n    for (uint256 _i; _i < _il; _i++) {\n      uint256 _transferAmt = _firstIn\n        ? getInitialAmount(_token, _amount, indexTokens[_i].token)\n        : (IERC20(indexTokens[_i].token).balanceOf(address(this)) *\n          _tokenAmtSupplyRatioX96) / FixedPoint96.Q96;\n      _transferFromAndValidate(\n        IERC20(indexTokens[_i].token),\n        _msgSender(),\n        _transferAmt\n      );\n    }\n    _bond();\n    emit Bond(_msgSender(), _token, _amount, _tokensMinted);\n  }\n\n  function debond(\n    uint256 _amount,\n    address[] memory,\n    uint8[] memory\n  ) external override lock noSwapOrFee {\n    uint256 _amountAfterFee = _isLastOut(_amount)\n      ? _amount\n      : (_amount * (DEN - fees.debond)) / DEN;\n    uint256 _percAfterFeeX96 = (_amountAfterFee * FixedPoint96.Q96) /\n      totalSupply();\n    super._transfer(_msgSender(), address(this), _amount);\n    _burn(address(this), _amountAfterFee);\n    _processBurnFee(_amount - _amountAfterFee);\n    uint256 _il = indexTokens.length;\n    for (uint256 _i; _i < _il; _i++) {\n      uint256 _tokenSupply = IERC20(indexTokens[_i].token).balanceOf(\n        address(this)\n      );\n      uint256 _debondAmount = (_tokenSupply * _percAfterFeeX96) /\n        FixedPoint96.Q96;\n      if (_debondAmount > 0) {\n        IERC20(indexTokens[_i].token).safeTransfer(_msgSender(), _debondAmount);\n      }\n    }\n    // an arbitrage path of buy pTKN > debond > sell TKN does not trigger rewards\n    // so let's trigger processing here at debond to keep things moving along\n    _processPreSwapFeesAndSwap();\n    emit Debond(_msgSender(), _amount);\n  }\n\n  function getInitialAmount(\n    address _sourceToken,\n    uint256 _sourceAmount,\n    address _targetToken\n  ) public view override returns (uint256) {\n    uint256 _sourceTokenIdx = _fundTokenIdx[_sourceToken];\n    uint256 _targetTokenIdx = _fundTokenIdx[_targetToken];\n    return\n      (_sourceAmount *\n        indexTokens[_targetTokenIdx].weighting *\n        10 ** IERC20Metadata(_targetToken).decimals()) /\n      indexTokens[_sourceTokenIdx].weighting /\n      10 ** IERC20Metadata(_sourceToken).decimals();\n  }\n\n  /// @notice This is used as a frontend helper but is NOT safe to be used as an oracle.\n  function getTokenPriceUSDX96(\n    address _token\n  ) external view override returns (uint256) {\n    return _getTokenPriceUSDX96(_token);\n  }\n\n  /// @notice This is used as a frontend helper but is NOT safe to be used as an oracle.\n  function getIdxPriceUSDX96()\n    external\n    view\n    override\n    returns (uint256, uint256)\n  {\n    uint256 _priceX96;\n    uint256 _X96_2 = 2 ** (96 / 2);\n    uint256 _il = indexTokens.length;\n    for (uint256 _i; _i < _il; _i++) {\n      uint256 _tokenPriceUSDX96_2 = _getTokenPriceUSDX96(\n        indexTokens[_i].token\n      ) / _X96_2;\n      _priceX96 +=\n        (_tokenPriceUSDX96_2 * indexTokens[_i].q1) /\n        10 ** IERC20Metadata(indexTokens[_i].token).decimals() /\n        _X96_2;\n    }\n    return (0, _priceX96);\n  }\n}\n"
      }
    },
    "settings": {
      "metadata": {
        "bytecodeHash": "none"
      },
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}