creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/TradeIssuerV3.sol": {
        "content": "/**\n *     SPDX-License-Identifier: Apache License 2.0\n *\n *     Copyright 2021 Index Cooperative\n *     Copyright 2024 Smash Works Inc.\n *\n *     Licensed under the Apache License, Version 2.0 (the \"License\");\n *     you may not use this file except in compliance with the License.\n *     You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n *     Unless required by applicable law or agreed to in writing, software\n *     distributed under the License is distributed on an \"AS IS\" BASIS,\n *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *     See the License for the specific language governing permissions and\n *     limitations under the License.\n *\n *     NOTICE\n *\n *     This is a modified code from Index Cooperative Inc. found at\n *\n *     https://github.com/IndexCoop/index-coop-smart-contracts\n *\n *     All changes made by Smash Works Inc. are described and documented at\n *\n *     https://docs.arch.finance/chambers\n *\n *\n *             %@@@@@\n *          @@@@@@@@@@@\n *        #@@@@@     @@@           @@                   @@\n *       @@@@@@       @@@         @@@@                  @@\n *      @@@@@@         @@        @@  @@    @@@@@ @@@@@  @@@*@@\n *     .@@@@@          @@@      @@@@@@@@   @@    @@     @@  @@\n *     @@@@@(       (((((      @@@    @@@  @@    @@@@@  @@  @@\n *    @@@@@@   (((((((\n *    @@@@@#(((((((\n *    @@@@@(((((\n *      @@@((\n */\npragma solidity ^0.8.21;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\nimport { IChamber } from \"chambers/interfaces/IChamber.sol\";\nimport { IChamberGod } from \"chambers/interfaces/IChamberGod.sol\";\nimport { IIssuerWizard } from \"chambers/interfaces/IIssuerWizard.sol\";\n\nimport { ReentrancyGuard } from \"solmate/utils/ReentrancyGuard.sol\";\nimport { WETH } from \"solmate/tokens/WETH.sol\";\n\nimport { ITradeIssuerV3 } from \"./interfaces/ITradeIssuerV3.sol\";\n\ncontract TradeIssuerV3 is ITradeIssuerV3, Ownable, ReentrancyGuard {\n    /*//////////////////////////////////////////////////////////////\n                              LIBRARIES\n    //////////////////////////////////////////////////////////////*/\n\n    using Address for address;\n    using Address for address payable;\n    using EnumerableSet for EnumerableSet.AddressSet;\n    using SafeERC20 for IERC20;\n\n    /*//////////////////////////////////////////////////////////////\n                                  STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    EnumerableSet.AddressSet private allowedTargets;\n    address public immutable wrappedNativeToken;\n    IChamberGod public chamberGod;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @param _wrappedNativeToken        Wrapped network native token\n     */\n    constructor(address _wrappedNativeToken, address _chamberGod) Ownable(msg.sender) {\n        wrappedNativeToken = _wrappedNativeToken;\n        chamberGod = IChamberGod(_chamberGod);\n    }\n\n    receive() external payable { }\n\n    /*//////////////////////////////////////////////////////////////\n                            EXTERNAL FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * Returns an array of the allowed targets for the trade issuer\n     *\n     * @return address[]     An address array containing the allowed targets\n     */\n    function getAllowedTargets() external view returns (address[] memory) {\n        return allowedTargets.values();\n    }\n\n    /**\n     * Checks if the address is an allowed target\n     *\n     * @param _target    The address to check\n     *\n     * @return bool      True if the address is a valid target\n     */\n    function isAllowedTarget(address _target) public view returns (bool) {\n        return allowedTargets.contains(_target);\n    }\n\n    /**\n     * Allows the trade issuer to perform low level calls to the specified target\n     *\n     * @param _target    The address of the target to allow\n     */\n    function addTarget(address _target) external onlyOwner nonReentrant {\n        if (_target == address(0)) {\n            revert InvalidTarget(_target);\n        }\n        if (isAllowedTarget(address(_target))) revert TargetAlreadyAllowed();\n\n        if (!allowedTargets.add(_target)) revert CannotAllowTarget();\n\n        emit AllowedTargetAdded(_target);\n    }\n\n    /**\n     * Removes the ability to perform low level calls to the target\n     *\n     * @param _target    The address of the target to remove\n     */\n    function removeTarget(address _target) external onlyOwner nonReentrant {\n        if (!isAllowedTarget(_target)) {\n            revert InvalidTarget(_target);\n        }\n\n        if (!allowedTargets.remove(_target)) revert CannotRemoveTarget();\n\n        emit AllowedTargetRemoved(_target);\n    }\n\n    /**\n     * Transfer the total balance of the specified stucked token to the owner address\n     *\n     * @param _tokenToWithdraw     The ERC20 token address to withdraw\n     */\n    function transferERC20ToOwner(address _tokenToWithdraw) external onlyOwner nonReentrant {\n        if (IERC20(_tokenToWithdraw).balanceOf(address(this)) < 1) revert ZeroBalanceAsset();\n\n        IERC20(_tokenToWithdraw).safeTransfer(\n            owner(), IERC20(_tokenToWithdraw).balanceOf(address(this))\n        );\n    }\n\n    /**\n     * Transfer all stucked Ether to the owner of the contract\n     */\n    function transferEthToOwner() external onlyOwner nonReentrant {\n        if (address(this).balance < 1) revert ZeroBalanceAsset();\n        payable(owner()).transfer(address(this).balance);\n    }\n\n    /**\n     * Mints the specified amount of chamber token and sends them to the msg.sender using an ERC20\n     * token as input. Unspent baseToken is also transferred back to the sender.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _issuerWizard                 Issuer wizard that'll be called for mint.\n     * @param _baseToken                    The token that will be used to get the underlying assets.\n     * @param _maxPayAmount                 The maximum amount of the baseToken to be used for the mint.\n     * @param _mintAmount                   Chamber tokens amount to mint.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     *\n     * @return baseTokenUsed                Total amount of the base token used for the mint.\n     *\n     */\n    function mintFromToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        IERC20 _baseToken,\n        uint256 _maxPayAmount,\n        uint256 _mintAmount\n    ) external nonReentrant returns (uint256 baseTokenUsed) {\n        if (_mintAmount == 0) revert ZeroChamberAmount();\n        if (_maxPayAmount == 0) revert ZeroBaseTokenSent();\n        if (!chamberGod.isWizard(address(_issuerWizard))) revert InvalidWizard();\n        if (!chamberGod.isChamber(address(_chamber))) revert InvalidChamber();\n\n        _baseToken.safeTransferFrom(msg.sender, address(this), _maxPayAmount);\n\n        baseTokenUsed = _mint(\n            _chamber, IERC20(_baseToken), _issuerWizard, _mintAmount, _contractCallInstructions\n        );\n\n        if (_maxPayAmount < baseTokenUsed) revert OversoldBaseToken();\n\n        uint256 remainingBaseToken = _maxPayAmount - baseTokenUsed;\n\n        _baseToken.safeTransfer(msg.sender, remainingBaseToken);\n\n        IERC20(address(_chamber)).safeTransfer(msg.sender, _mintAmount);\n\n        emit TradeIssuerTokenMinted(\n            address(_chamber), msg.sender, address(_baseToken), baseTokenUsed, _mintAmount\n        );\n\n        return baseTokenUsed;\n    }\n\n    /**\n     * Mints the specified amount of chamber token and sends them to the msg.sender using the network\n     * native token as input. Unspent native token is also transferred back to the sender.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _issuerWizard                 Issuer wizard that'll be called for mint.\n     * @param _mintAmount                   Chamber tokens amount to mint.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     *\n     * @return wrappedNativeTokenUsed       Total amount of the wrapped native token used for the mint.\n     *\n     */\n    function mintFromNativeToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        uint256 _mintAmount\n    ) external payable nonReentrant returns (uint256 wrappedNativeTokenUsed) {\n        if (_mintAmount == 0) revert ZeroChamberAmount();\n        if (msg.value == 0) revert ZeroNativeTokenSent();\n        if (!chamberGod.isWizard(address(_issuerWizard))) revert InvalidWizard();\n        if (!chamberGod.isChamber(address(_chamber))) revert InvalidChamber();\n\n        WETH(payable(wrappedNativeToken)).deposit{ value: msg.value }();\n\n        wrappedNativeTokenUsed = _mint(\n            _chamber,\n            IERC20(wrappedNativeToken),\n            _issuerWizard,\n            _mintAmount,\n            _contractCallInstructions\n        );\n\n        if (msg.value < wrappedNativeTokenUsed) revert OversoldBaseToken();\n\n        uint256 remainingWrappedNativeToken = msg.value - wrappedNativeTokenUsed;\n\n        WETH(payable(wrappedNativeToken)).withdraw(remainingWrappedNativeToken);\n        payable(msg.sender).sendValue(remainingWrappedNativeToken);\n\n        IERC20(address(_chamber)).safeTransfer(msg.sender, _mintAmount);\n\n        emit TradeIssuerTokenMinted(\n            address(_chamber),\n            msg.sender,\n            address(wrappedNativeToken),\n            wrappedNativeTokenUsed,\n            _mintAmount\n        );\n\n        return wrappedNativeTokenUsed;\n    }\n\n    /**\n     * Redeems the specified amount of chamber token for the required baseToken and sends it to the\n     * msg.sender.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _issuerWizard                 Issuer wizard that'll be called for redeem.\n     * @param _baseToken                    The token that it will be sent to the msg.sender.\n     * @param _minReceiveAmount             The minimum amount of the baseToken to be received.\n     * @param _redeemAmount                 Chamber tokens amount to redeem.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     *\n     * @return baseTokenReturned            Total baseToken amount sent to the msg.sender.\n     *\n     */\n    function redeemToToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        IERC20 _baseToken,\n        uint256 _minReceiveAmount,\n        uint256 _redeemAmount\n    ) external nonReentrant returns (uint256 baseTokenReturned) {\n        if (_redeemAmount == 0) revert ZeroChamberAmount();\n        if (!chamberGod.isWizard(address(_issuerWizard))) revert InvalidWizard();\n        if (!chamberGod.isChamber(address(_chamber))) revert InvalidChamber();\n\n        IERC20(address(_chamber)).safeTransferFrom(msg.sender, address(this), _redeemAmount);\n\n        baseTokenReturned =\n            _redeem(_chamber, _baseToken, _issuerWizard, _redeemAmount, _contractCallInstructions);\n\n        if (baseTokenReturned < _minReceiveAmount) {\n            revert RedeemedForLessTokens();\n        }\n\n        _baseToken.safeTransfer(msg.sender, baseTokenReturned);\n\n        emit TradeIssuerTokenRedeemed(\n            address(_chamber), msg.sender, address(_baseToken), baseTokenReturned, _redeemAmount\n        );\n\n        return baseTokenReturned;\n    }\n\n    /**\n     * Redeems the specified amount of chamber token for the network's native token and sends it to the\n     * msg.sender.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _issuerWizard                 Issuer wizard that'll be called for redeem.\n     * @param _minReceiveAmount             The minimum amount of the baseToken to be received.\n     * @param _redeemAmount                 Chamber tokens amount to redeem.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     *\n     * @return wrappedNativeTokenReturned   Total native token amount sent to the msg.sender.\n     *\n     */\n    function redeemToNativeToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        uint256 _minReceiveAmount,\n        uint256 _redeemAmount\n    ) external nonReentrant returns (uint256 wrappedNativeTokenReturned) {\n        if (_redeemAmount == 0) revert ZeroChamberAmount();\n        if (!chamberGod.isWizard(address(_issuerWizard))) revert InvalidWizard();\n        if (!chamberGod.isChamber(address(_chamber))) revert InvalidChamber();\n\n        IERC20(address(_chamber)).safeTransferFrom(msg.sender, address(this), _redeemAmount);\n\n        wrappedNativeTokenReturned = _redeem(\n            _chamber,\n            IERC20(wrappedNativeToken),\n            _issuerWizard,\n            _redeemAmount,\n            _contractCallInstructions\n        );\n\n        if (wrappedNativeTokenReturned < _minReceiveAmount) {\n            revert RedeemedForLessTokens();\n        }\n\n        WETH(payable(wrappedNativeToken)).withdraw(wrappedNativeTokenReturned);\n        payable(msg.sender).sendValue(wrappedNativeTokenReturned);\n\n        emit TradeIssuerTokenRedeemed(\n            address(_chamber),\n            msg.sender,\n            address(wrappedNativeToken),\n            wrappedNativeTokenReturned,\n            _redeemAmount\n        );\n\n        return wrappedNativeTokenReturned;\n    }\n\n    /**\n     * Redeems the specified amount of chamber token, performs the specified instructions and mints another chamber token\n     *\n     * @param _chamberToRedeem              Chamber address.\n     * @param _chamberToMint                Chamber address.\n     * @param _issuerWizard                 Issuer wizard that'll be called for redeem.\n     * @param _redeemAmount                 Chamber tokens amount to redeem.\n     * @param _mintAmount                   The amount of the chamber to mint to be received.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets of the chamber token to mint.\n     */\n    function redeemAndMint(\n        IChamber _chamberToRedeem,\n        uint256 _redeemAmount,\n        IChamber _chamberToMint,\n        uint256 _mintAmount,\n        IIssuerWizard _issuerWizard,\n        ContractCallInstruction[] memory _contractCallInstructions\n    ) external nonReentrant {\n        if (_redeemAmount == 0) revert ZeroChamberAmount();\n        if (_mintAmount == 0) revert ZeroChamberAmount();\n        if (!chamberGod.isWizard(address(_issuerWizard))) revert InvalidWizard();\n        if (!chamberGod.isChamber(address(_chamberToRedeem))) revert InvalidChamber();\n        if (!chamberGod.isChamber(address(_chamberToMint))) revert InvalidChamber();\n\n        IERC20(address(_chamberToRedeem)).safeTransferFrom(msg.sender, address(this), _redeemAmount);\n\n        _redeemAndMint(\n            _chamberToRedeem,\n            _chamberToMint,\n            _issuerWizard,\n            _redeemAmount,\n            _mintAmount,\n            _contractCallInstructions\n        );\n\n        IERC20(address(_chamberToMint)).safeTransfer(msg.sender, _mintAmount);\n\n        emit TradeIssuerTokenRedeemedAndMinted(\n            msg.sender,\n            address(_chamberToRedeem),\n            address(_chamberToMint),\n            _redeemAmount,\n            _mintAmount\n        );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            INTERNAL FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * Internal function in charge of the generic mint. The main objective is to get the chamber tokens.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _baseToken                    The token that will be used to get the underlying assets.\n     * @param _issuerWizard                 Issuer wizard that'll be called for mint.\n     * @param _mintAmount                Chamber tokens amount to mint.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     *\n     * @return baseTokenUsed                Total amount of the base token used for the mint.\n     *\n     */\n    function _mint(\n        IChamber _chamber,\n        IERC20 _baseToken,\n        IIssuerWizard _issuerWizard,\n        uint256 _mintAmount,\n        ContractCallInstruction[] memory _contractCallInstructions\n    ) internal returns (uint256 baseTokenUsed) {\n        uint256 baseTokenBalanceBefore = _baseToken.balanceOf(address(this));\n\n        _executeInstructions(_contractCallInstructions);\n\n        _checkAndIncreaseAllowanceOfConstituents(_chamber, _issuerWizard, _mintAmount);\n\n        _issuerWizard.issue(_chamber, _mintAmount);\n\n        baseTokenUsed = baseTokenBalanceBefore - _baseToken.balanceOf(address(this));\n\n        return baseTokenUsed;\n    }\n\n    /**\n     * Internal function in charge of the generic redeem. The main objective is to get the base token\n     * from the chamber token.\n     *\n     * @param _chamber                      Chamber address.\n     * @param _baseToken                    The token that will be used to get the underlying assets.\n     * @param _issuerWizard                 Issuer wizard that'll be called for redeem.\n     * @param _redeemAmount                 Chamber tokens amount to redeem.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the _baseToken assets.\n     *\n     * @return totalBaseTokenReturned       Total amount of the base that will be sent to the msg.sender.\n     *\n     */\n    function _redeem(\n        IChamber _chamber,\n        IERC20 _baseToken,\n        IIssuerWizard _issuerWizard,\n        uint256 _redeemAmount,\n        ContractCallInstruction[] memory _contractCallInstructions\n    ) internal returns (uint256 totalBaseTokenReturned) {\n        uint256 baseTokenBalanceBefore = _baseToken.balanceOf(address(this));\n\n        _issuerWizard.redeem(_chamber, _redeemAmount);\n\n        _executeInstructions(_contractCallInstructions);\n\n        totalBaseTokenReturned = _baseToken.balanceOf(address(this)) - baseTokenBalanceBefore;\n\n        return totalBaseTokenReturned;\n    }\n\n    /**\n     * Internal function in charge of performing a redeem, execute instructions and mint. The main objective is to redeem a chamber\n     * exchange its components and mint another chamber\n     *\n     * @param _chamberToRedeem              Chamber to redeem.\n     * @param _chamberToMint                Chamber to mint.\n     * @param _issuerWizard                 Issuer wizard that'll be called for redeem.\n     * @param _redeemAmount                 Chamber tokens amount to redeem.\n     * @param _minimumMintAmount            Chamber tokens amount to mint.\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the mintChamber constituents.\n     */\n    function _redeemAndMint(\n        IChamber _chamberToRedeem,\n        IChamber _chamberToMint,\n        IIssuerWizard _issuerWizard,\n        uint256 _redeemAmount,\n        uint256 _minimumMintAmount,\n        ContractCallInstruction[] memory _contractCallInstructions\n    ) internal {\n        _issuerWizard.redeem(_chamberToRedeem, _redeemAmount);\n\n        _executeInstructions(_contractCallInstructions);\n\n        _checkAndIncreaseAllowanceOfConstituents(_chamberToMint, _issuerWizard, _minimumMintAmount);\n\n        _issuerWizard.issue(_chamberToMint, _minimumMintAmount);\n    }\n\n    /**\n     * Executes the array of instructions and verifies that the correct amount of each token\n     * from the instruction is purchased.\n     *\n     * @param _contractCallInstructions     Instruction array that will be executed in order to get\n     *                                      the underlying assets.\n     */\n    function _executeInstructions(ContractCallInstruction[] memory _contractCallInstructions)\n        internal\n    {\n        for (uint256 i = 0; i < _contractCallInstructions.length; i++) {\n            ContractCallInstruction memory currentInstruction = _contractCallInstructions[i];\n\n            uint256 buyTokenBalanceBefore = currentInstruction._buyToken.balanceOf(address(this));\n\n            _checkAndIncreaseAllowance(\n                address(currentInstruction._sellToken),\n                currentInstruction._allowanceTarget,\n                currentInstruction._sellAmount\n            );\n\n            _fillQuote(currentInstruction._target, currentInstruction._callData);\n\n            uint256 buyTokenAmountBought =\n                currentInstruction._buyToken.balanceOf(address(this)) - buyTokenBalanceBefore;\n            if (currentInstruction._minBuyAmount > buyTokenAmountBought) {\n                revert UnderboughtAsset(\n                    currentInstruction._buyToken, currentInstruction._minBuyAmount\n                );\n            }\n        }\n    }\n\n    /**\n     * Execute a contract call\n     *\n     * @param _callData       CallData to be executed on a allowed Target\n     *\n     * @return response       Response from the low-level call\n     */\n    function _fillQuote(address _target, bytes memory _callData)\n        internal\n        returns (bytes memory response)\n    {\n        if (!isAllowedTarget(_target)) revert InvalidTarget(_target);\n        response = _target.functionCall(_callData);\n        if (response.length == 0) revert LowLevelFunctionCallFailed();\n        return (response);\n    }\n\n    /**\n     * Checks the allowance for issuance of a chamberToken, if allowance is not enough it's increased to max.\n     *\n     * @param _chamber          Chamber token address for mint.\n     * @param _issuerWizard     Issuer wizard used at _chamber.\n     * @param _mintAmount    Amount of the chamber token to mint.\n     */\n    function _checkAndIncreaseAllowanceOfConstituents(\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        uint256 _mintAmount\n    ) internal {\n        (address[] memory requiredConstituents, uint256[] memory requiredConstituentsQuantities) =\n            _issuerWizard.getConstituentsQuantitiesForIssuance(_chamber, _mintAmount);\n\n        for (uint256 i = 0; i < requiredConstituents.length; i++) {\n            if (\n                IERC20(requiredConstituents[i]).balanceOf(address(this))\n                    < requiredConstituentsQuantities[i]\n            ) {\n                revert UnderboughtConstituent(\n                    IERC20(requiredConstituents[i]), requiredConstituentsQuantities[i]\n                );\n            }\n            _checkAndIncreaseAllowance(\n                requiredConstituents[i], address(_issuerWizard), requiredConstituentsQuantities[i]\n            );\n        }\n    }\n\n    /**\n     * For the specified token and amount, checks the allowance between the TraderIssuer and _target.\n     * If not enough, it sets the maximum.\n     *\n     * @param _tokenAddress     Address of the token that will be used.\n     * @param _target           Target address of the allowance.\n     * @param _requiredAmount   Required allowance for the operation.\n     */\n    function _checkAndIncreaseAllowance(\n        address _tokenAddress,\n        address _target,\n        uint256 _requiredAmount\n    ) internal {\n        if (_requiredAmount == 0) revert ZeroRequiredAmount();\n        uint256 currentAllowance = IERC20(_tokenAddress).allowance(address(this), _target);\n        if (currentAllowance < _requiredAmount) {\n            IERC20(_tokenAddress).safeIncreaseAllowance(\n                _target, type(uint256).max - currentAllowance\n            );\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../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 * The initial owner is set to the address provided by the deployer. This can\n * 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    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\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        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\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        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\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 value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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 value) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 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 An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, 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        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\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.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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 success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) 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 FailedInnerCall();\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes32 value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"
      },
      "lib/chambers/src/interfaces/IChamber.sol": {
        "content": "/**\n *     SPDX-License-Identifier: Apache License 2.0\n *\n *     Copyright 2018 Set Labs Inc.\n *     Copyright 2022 Smash Works Inc.\n *\n *     Licensed under the Apache License, Version 2.0 (the \"License\");\n *     you may not use this file except in compliance with the License.\n *     You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n *     Unless required by applicable law or agreed to in writing, software\n *     distributed under the License is distributed on an \"AS IS\" BASIS,\n *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *     See the License for the specific language governing permissions and\n *     limitations under the License.\n *\n *     NOTICE\n *\n *     This is a modified code from Set Labs Inc. found at\n *\n *     https://github.com/SetProtocol/set-protocol-contracts\n *\n *     All changes made by Smash Works Inc. are described and documented at\n *\n *     https://docs.arch.finance/chambers\n *\n *\n *             %@@@@@\n *          @@@@@@@@@@@\n *        #@@@@@     @@@           @@                   @@\n *       @@@@@@       @@@         @@@@                  @@\n *      @@@@@@         @@        @@  @@    @@@@@ @@@@@  @@@*@@\n *     .@@@@@          @@@      @@@@@@@@   @@    @@     @@  @@\n *     @@@@@(       (((((      @@@    @@@  @@    @@@@@  @@  @@\n *    @@@@@@   (((((((\n *    @@@@@#(((((((\n *    @@@@@(((((\n *      @@@((\n */\npragma solidity ^0.8.17.0;\n\ninterface IChamber {\n    /*//////////////////////////////////////////////////////////////\n                                 ENUMS\n    //////////////////////////////////////////////////////////////*/\n\n    enum ChamberState {\n        LOCKED,\n        UNLOCKED\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event ManagerAdded(address indexed _manager);\n\n    event ManagerRemoved(address indexed _manager);\n\n    event ConstituentAdded(address indexed _constituent);\n\n    event ConstituentRemoved(address indexed _constituent);\n\n    event WizardAdded(address indexed _wizard);\n\n    event WizardRemoved(address indexed _wizard);\n\n    event AllowedContractAdded(address indexed _allowedContract);\n\n    event AllowedContractRemoved(address indexed _allowedContract);\n\n    /*//////////////////////////////////////////////////////////////\n                               CHAMBER MANAGEMENT\n    //////////////////////////////////////////////////////////////*/\n\n    function addConstituent(address _constituent) external;\n\n    function removeConstituent(address _constituent) external;\n\n    function isManager(address _manager) external view returns (bool);\n\n    function isWizard(address _wizard) external view returns (bool);\n\n    function isConstituent(address _constituent) external view returns (bool);\n\n    function addManager(address _manager) external;\n\n    function removeManager(address _manager) external;\n\n    function addWizard(address _wizard) external;\n\n    function removeWizard(address _wizard) external;\n\n    function getConstituentsAddresses() external view returns (address[] memory);\n\n    function getQuantities() external view returns (uint256[] memory);\n\n    function getConstituentQuantity(address _constituent) external view returns (uint256);\n\n    function getWizards() external view returns (address[] memory);\n\n    function getManagers() external view returns (address[] memory);\n\n    function getAllowedContracts() external view returns (address[] memory);\n\n    function mint(address _recipient, uint256 _quantity) external;\n\n    function burn(address _from, uint256 _quantity) external;\n\n    function withdrawTo(address _constituent, address _recipient, uint256 _quantity) external;\n\n    function updateQuantities() external;\n\n    function lockChamber() external;\n\n    function unlockChamber() external;\n\n    function addAllowedContract(address target) external;\n\n    function removeAllowedContract(address target) external;\n\n    function isAllowedContract(address _target) external returns (bool);\n\n    function executeTrade(\n        address _sellToken,\n        uint256 _sellQuantity,\n        address _buyToken,\n        uint256 _minBuyQuantity,\n        bytes memory _data,\n        address payable _target,\n        address _allowanceTarget\n    ) external returns (uint256 tokenAmountBought);\n}\n"
      },
      "lib/chambers/src/interfaces/IChamberGod.sol": {
        "content": "/**\n *     SPDX-License-Identifier: Apache License 2.0\n *\n *     Copyright 2018 Set Labs Inc.\n *     Copyright 2022 Smash Works Inc.\n *\n *     Licensed under the Apache License, Version 2.0 (the \"License\");\n *     you may not use this file except in compliance with the License.\n *     You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n *     Unless required by applicable law or agreed to in writing, software\n *     distributed under the License is distributed on an \"AS IS\" BASIS,\n *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *     See the License for the specific language governing permissions and\n *     limitations under the License.\n *\n *     NOTICE\n *\n *     This is a modified code from Set Labs Inc. found at\n *\n *     https://github.com/SetProtocol/set-protocol-contracts\n *\n *     All changes made by Smash Works Inc. are described and documented at\n *\n *     https://docs.arch.finance/chambers\n *\n *\n *             %@@@@@\n *          @@@@@@@@@@@\n *        #@@@@@     @@@           @@                   @@\n *       @@@@@@       @@@         @@@@                  @@\n *      @@@@@@         @@        @@  @@    @@@@@ @@@@@  @@@*@@\n *     .@@@@@          @@@      @@@@@@@@   @@    @@     @@  @@\n *     @@@@@(       (((((      @@@    @@@  @@    @@@@@  @@  @@\n *    @@@@@@   (((((((\n *    @@@@@#(((((((\n *    @@@@@(((((\n *      @@@((\n */\npragma solidity ^0.8.17.0;\n\ninterface IChamberGod {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event ChamberCreated(address indexed _chamber, address _owner, string _name, string _symbol);\n\n    event WizardAdded(address indexed _wizard);\n\n    event WizardRemoved(address indexed _wizard);\n\n    event AllowedContractAdded(address indexed _allowedContract);\n\n    event AllowedContractRemoved(address indexed _allowedContract);\n\n    /*//////////////////////////////////////////////////////////////\n                            CHAMBER GOD LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function createChamber(\n        string memory _name,\n        string memory _symbol,\n        address[] memory _constituents,\n        uint256[] memory _quantities,\n        address[] memory _wizards,\n        address[] memory _managers\n    ) external returns (address);\n\n    function getWizards() external view returns (address[] memory);\n\n    function getChambers() external view returns (address[] memory);\n\n    function isWizard(address _wizard) external view returns (bool);\n\n    function isChamber(address _chamber) external view returns (bool);\n\n    function addWizard(address _wizard) external;\n\n    function removeWizard(address _wizard) external;\n\n    function getAllowedContracts() external view returns (address[] memory);\n\n    function addAllowedContract(address _target) external;\n\n    function removeAllowedContract(address _target) external;\n\n    function isAllowedContract(address _target) external view returns (bool);\n}\n"
      },
      "lib/chambers/src/interfaces/IIssuerWizard.sol": {
        "content": "/**\n *     SPDX-License-Identifier: Apache License 2.0\n *\n *     Copyright 2018 Set Labs Inc.\n *     Copyright 2022 Smash Works Inc.\n *\n *     Licensed under the Apache License, Version 2.0 (the \"License\");\n *     you may not use this file except in compliance with the License.\n *     You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n *     Unless required by applicable law or agreed to in writing, software\n *     distributed under the License is distributed on an \"AS IS\" BASIS,\n *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *     See the License for the specific language governing permissions and\n *     limitations under the License.\n *\n *     NOTICE\n *\n *     This is a modified code from Set Labs Inc. found at\n *\n *     https://github.com/SetProtocol/set-protocol-contracts\n *\n *     All changes made by Smash Works Inc. are described and documented at\n *\n *     https://docs.arch.finance/chambers\n *\n *\n *             %@@@@@\n *          @@@@@@@@@@@\n *        #@@@@@     @@@           @@                   @@\n *       @@@@@@       @@@         @@@@                  @@\n *      @@@@@@         @@        @@  @@    @@@@@ @@@@@  @@@*@@\n *     .@@@@@          @@@      @@@@@@@@   @@    @@     @@  @@\n *     @@@@@(       (((((      @@@    @@@  @@    @@@@@  @@  @@\n *    @@@@@@   (((((((\n *    @@@@@#(((((((\n *    @@@@@(((((\n *      @@@((\n */\npragma solidity ^0.8.17.0;\n\nimport {IChamber} from \"./IChamber.sol\";\n\ninterface IIssuerWizard {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event ChamberTokenIssued(address indexed chamber, address indexed recipient, uint256 quantity);\n\n    event ChamberTokenRedeemed(\n        address indexed chamber, address indexed recipient, uint256 quantity\n    );\n\n    /*//////////////////////////////////////////////////////////////\n                                FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function getConstituentsQuantitiesForIssuance(IChamber chamber, uint256 mintQuantity)\n        external\n        view\n        returns (address[] memory, uint256[] memory);\n\n    function getConstituentsQuantitiesForRedeem(IChamber chamber, uint256 redeemQuantity)\n        external\n        view\n        returns (address[] memory, uint256[] memory);\n\n    function issue(IChamber chamber, uint256 quantity) external;\n\n    function redeem(IChamber _chamber, uint256 _quantity) external;\n}\n"
      },
      "lib/solmate/src/utils/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Gas optimized reentrancy protection for smart contracts.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)\nabstract contract ReentrancyGuard {\n    uint256 private locked = 1;\n\n    modifier nonReentrant() virtual {\n        require(locked == 1, \"REENTRANCY\");\n\n        locked = 2;\n\n        _;\n\n        locked = 1;\n    }\n}\n"
      },
      "lib/solmate/src/tokens/WETH.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"./ERC20.sol\";\n\nimport {SafeTransferLib} from \"../utils/SafeTransferLib.sol\";\n\n/// @notice Minimalist and modern Wrapped Ether implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)\n/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)\ncontract WETH is ERC20(\"Wrapped Ether\", \"WETH\", 18) {\n    using SafeTransferLib for address;\n\n    event Deposit(address indexed from, uint256 amount);\n\n    event Withdrawal(address indexed to, uint256 amount);\n\n    function deposit() public payable virtual {\n        _mint(msg.sender, msg.value);\n\n        emit Deposit(msg.sender, msg.value);\n    }\n\n    function withdraw(uint256 amount) public virtual {\n        _burn(msg.sender, amount);\n\n        emit Withdrawal(msg.sender, amount);\n\n        msg.sender.safeTransferETH(amount);\n    }\n\n    receive() external payable virtual {\n        deposit();\n    }\n}\n"
      },
      "src/interfaces/ITradeIssuerV3.sol": {
        "content": "/**\n *     SPDX-License-Identifier: Apache License 2.0\n *\n *     Copyright 2021 Index Cooperative\n *     Copyright 2024 Smash Works Inc.\n *\n *     Licensed under the Apache License, Version 2.0 (the \"License\");\n *     you may not use this file except in compliance with the License.\n *     You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n *     Unless required by applicable law or agreed to in writing, software\n *     distributed under the License is distributed on an \"AS IS\" BASIS,\n *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *     See the License for the specific language governing permissions and\n *     limitations under the License.\n *\n *     NOTICE\n *\n *     This is a modified code from Index Cooperative found at\n *\n *     https://github.com/IndexCoop/index-coop-smart-contracts\n *\n *     All changes made by Smash Works Inc. are described and documented at\n *\n *     https://docs.arch.finance/chambers\n *\n *\n *             %@@@@@\n *          @@@@@@@@@@@\n *        #@@@@@     @@@           @@                   @@\n *       @@@@@@       @@@         @@@@                  @@\n *      @@@@@@         @@        @@  @@    @@@@@ @@@@@  @@@*@@\n *     .@@@@@          @@@      @@@@@@@@   @@    @@     @@  @@\n *     @@@@@(       (((((      @@@    @@@  @@    @@@@@  @@  @@\n *    @@@@@@   (((((((\n *    @@@@@#(((((((\n *    @@@@@(((((\n *      @@@((\n */\npragma solidity ^0.8.21;\n\nimport { IChamber } from \"chambers/interfaces/IChamber.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IIssuerWizard } from \"chambers/interfaces/IIssuerWizard.sol\";\n\ninterface ITradeIssuerV3 {\n    /*//////////////////////////////////////////////////////////////\n                               STRUCTS\n    //////////////////////////////////////////////////////////////*/\n\n    struct ContractCallInstruction {\n        address payable _target;\n        address _allowanceTarget;\n        IERC20 _sellToken;\n        uint256 _sellAmount;\n        IERC20 _buyToken;\n        uint256 _minBuyAmount;\n        bytes _callData;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event AllowedTargetAdded(address indexed _target);\n\n    event AllowedTargetRemoved(address indexed _targer);\n\n    event TradeIssuerTokenMinted(\n        address indexed chamber,\n        address indexed recipient,\n        address indexed inputToken,\n        uint256 totalTokensUsed,\n        uint256 mintAmount\n    );\n\n    event TradeIssuerTokenRedeemed(\n        address indexed chamber,\n        address indexed recipient,\n        address indexed outputToken,\n        uint256 totalTokensReturned,\n        uint256 redeemAmount\n    );\n\n    event TradeIssuerTokenRedeemedAndMinted(\n        address indexed recipient,\n        address indexed chamberToRedeem,\n        address indexed chamberToMint,\n        uint256 redeemAmount,\n        uint256 mintAmount\n    );\n\n    /*//////////////////////////////////////////////////////////////\n                                ERRORS\n    //////////////////////////////////////////////////////////////*/\n\n    error CannotAllowTarget();\n\n    error CannotRemoveTarget();\n\n    error InvalidTarget(address target);\n\n    error LowLevelFunctionCallFailed();\n\n    error OversoldBaseToken();\n\n    error RedeemedForLessTokens();\n\n    error TargetAlreadyAllowed();\n\n    error UnderboughtAsset(IERC20 asset, uint256 buyAmount);\n\n    error UnderboughtConstituent(IERC20 asset, uint256 buyAmount);\n\n    error ZeroChamberAmount();\n\n    error ZeroBalanceAsset();\n\n    error ZeroNativeTokenSent();\n\n    error ZeroBaseTokenSent();\n\n    error ZeroRequiredAmount();\n\n    error InvalidWizard();\n\n    error InvalidChamber();\n\n    /*//////////////////////////////////////////////////////////////\n                                FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function getAllowedTargets() external returns (address[] memory);\n\n    function isAllowedTarget(address _target) external returns (bool);\n\n    function addTarget(address _target) external;\n\n    function removeTarget(address _target) external;\n\n    function transferERC20ToOwner(address _tokenToWithdraw) external;\n\n    function transferEthToOwner() external;\n\n    function mintFromToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        IERC20 _baseToken,\n        uint256 _maxPayAmount,\n        uint256 _chamberAmount\n    ) external returns (uint256 baseTokenUsed);\n\n    function mintFromNativeToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        uint256 _chamberAmount\n    ) external payable returns (uint256 wrappedNativeTokenUsed);\n\n    function redeemToToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        IERC20 _baseToken,\n        uint256 _minReceiveAmount,\n        uint256 _chamberAmount\n    ) external returns (uint256 baseTokenReturned);\n\n    function redeemToNativeToken(\n        ContractCallInstruction[] memory _contractCallInstructions,\n        IChamber _chamber,\n        IIssuerWizard _issuerWizard,\n        uint256 _minReceiveAmount,\n        uint256 _chamberAmount\n    ) external returns (uint256 wrappedNativeTokenReturned);\n\n    function redeemAndMint(\n        IChamber _chamberToRedeem,\n        uint256 _redeemAmount,\n        IChamber _chamberToMint,\n        uint256 _mintAmount,\n        IIssuerWizard _issuerWizard,\n        ContractCallInstruction[] memory _contractCallInstructions\n    ) external;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1363.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"
      },
      "lib/solmate/src/tokens/ERC20.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /*//////////////////////////////////////////////////////////////\n                            METADATA STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    uint8 public immutable decimals;\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC20 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public totalSupply;\n\n    mapping(address => uint256) public balanceOf;\n\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /*//////////////////////////////////////////////////////////////\n                            EIP-2612 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal immutable INITIAL_CHAIN_ID;\n\n    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n    mapping(address => uint256) public nonces;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) {\n        name = _name;\n        symbol = _symbol;\n        decimals = _decimals;\n\n        INITIAL_CHAIN_ID = block.chainid;\n        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               ERC20 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\n        allowance[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) public virtual returns (bool) {\n        balanceOf[msg.sender] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(msg.sender, to, amount);\n\n        return true;\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual returns (bool) {\n        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n        balanceOf[from] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        return true;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\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 {\n        require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            address recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\n                                    \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n                                ),\n                                owner,\n                                spender,\n                                value,\n                                nonces[owner]++,\n                                deadline\n                            )\n                        )\n                    )\n                ),\n                v,\n                r,\n                s\n            );\n\n            require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n            allowance[recoveredAddress][spender] = value;\n        }\n\n        emit Approval(owner, spender, value);\n    }\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n    }\n\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                    keccak256(bytes(name)),\n                    keccak256(\"1\"),\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 amount) internal virtual {\n        totalSupply += amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(address(0), to, amount);\n    }\n\n    function _burn(address from, uint256 amount) internal virtual {\n        balanceOf[from] -= amount;\n\n        // Cannot underflow because a user's balance\n        // will never be larger than the total supply.\n        unchecked {\n            totalSupply -= amount;\n        }\n\n        emit Transfer(from, address(0), amount);\n    }\n}\n"
      },
      "lib/solmate/src/utils/SafeTransferLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n    /*//////////////////////////////////////////////////////////////\n                             ETH OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function safeTransferETH(address to, uint256 amount) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and store if it succeeded or not.\n            success := call(gas(), to, amount, 0, 0, 0, 0)\n        }\n\n        require(success, \"ETH_TRANSFER_FAILED\");\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            ERC20 OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function safeTransferFrom(\n        ERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from\" argument.\n            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n            )\n        }\n\n        require(success, \"TRANSFER_FROM_FAILED\");\n    }\n\n    function safeTransfer(\n        ERC20 token,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        require(success, \"TRANSFER_FAILED\");\n    }\n\n    function safeApprove(\n        ERC20 token,\n        address to,\n        uint256 amount\n    ) internal {\n        bool success;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to\" argument.\n            mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument. Masking not required as it's a full 32 byte type.\n\n            success := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        require(success, \"APPROVE_FAILED\");\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/solmate/lib/ds-test/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "chambers/=lib/chambers/src/",
        "forge-std/=lib/forge-std/src/",
        "solmate/=lib/solmate/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": true,
      "libraries": {}
    }
  }}