creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@mimic-fi/v3-authorizer/contracts/Authorized.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\nimport './AuthorizedHelpers.sol';\nimport './interfaces/IAuthorized.sol';\nimport './interfaces/IAuthorizer.sol';\n\n/**\n * @title Authorized\n * @dev Implementation using an authorizer as its access-control mechanism. It offers `auth` and `authP` modifiers to\n * tag its own functions in order to control who can access them against the authorizer referenced.\n */\ncontract Authorized is IAuthorized, Initializable, AuthorizedHelpers {\n    // Authorizer reference\n    address public override authorizer;\n\n    /**\n     * @dev Modifier that should be used to tag protected functions\n     */\n    modifier auth() {\n        _authenticate(msg.sender, msg.sig);\n        _;\n    }\n\n    /**\n     * @dev Modifier that should be used to tag protected functions with params\n     */\n    modifier authP(uint256[] memory params) {\n        _authenticate(msg.sender, msg.sig, params);\n        _;\n    }\n\n    /**\n     * @dev Creates a new authorized contract. Note that initializers are disabled at creation time.\n     */\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @dev Initializes the authorized contract. It does call upper contracts initializers.\n     * @param _authorizer Address of the authorizer to be set\n     */\n    function __Authorized_init(address _authorizer) internal onlyInitializing {\n        __Authorized_init_unchained(_authorizer);\n    }\n\n    /**\n     * @dev Initializes the authorized contract. It does not call upper contracts initializers.\n     * @param _authorizer Address of the authorizer to be set\n     */\n    function __Authorized_init_unchained(address _authorizer) internal onlyInitializing {\n        authorizer = _authorizer;\n    }\n\n    /**\n     * @dev Reverts if `who` is not allowed to call `what`\n     * @param who Address to be authenticated\n     * @param what Function selector to be authenticated\n     */\n    function _authenticate(address who, bytes4 what) internal view {\n        _authenticate(who, what, new uint256[](0));\n    }\n\n    /**\n     * @dev Reverts if `who` is not allowed to call `what` with `how`\n     * @param who Address to be authenticated\n     * @param what Function selector to be authenticated\n     * @param how Params to be authenticated\n     */\n    function _authenticate(address who, bytes4 what, uint256[] memory how) internal view {\n        if (!_isAuthorized(who, what, how)) revert AuthSenderNotAllowed(who, what, how);\n    }\n\n    /**\n     * @dev Tells whether `who` has any permission on this contract\n     * @param who Address asking permissions for\n     */\n    function _hasPermissions(address who) internal view returns (bool) {\n        return IAuthorizer(authorizer).hasPermissions(who, address(this));\n    }\n\n    /**\n     * @dev Tells whether `who` is allowed to call `what`\n     * @param who Address asking permission for\n     * @param what Function selector asking permission for\n     */\n    function _isAuthorized(address who, bytes4 what) internal view returns (bool) {\n        return _isAuthorized(who, what, new uint256[](0));\n    }\n\n    /**\n     * @dev Tells whether `who` is allowed to call `what` with `how`\n     * @param who Address asking permission for\n     * @param what Function selector asking permission for\n     * @param how Params asking permission for\n     */\n    function _isAuthorized(address who, bytes4 what, uint256[] memory how) internal view returns (bool) {\n        return IAuthorizer(authorizer).isAuthorized(who, address(this), what, how);\n    }\n}\n"
      },
      "@mimic-fi/v3-authorizer/contracts/AuthorizedHelpers.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\n/**\n * @title AuthorizedHelpers\n * @dev Syntax sugar methods to operate with authorizer params easily\n */\ncontract AuthorizedHelpers {\n    function authParams(address p1) internal pure returns (uint256[] memory r) {\n        return authParams(uint256(uint160(p1)));\n    }\n\n    function authParams(bytes32 p1) internal pure returns (uint256[] memory r) {\n        return authParams(uint256(p1));\n    }\n\n    function authParams(uint256 p1) internal pure returns (uint256[] memory r) {\n        r = new uint256[](1);\n        r[0] = p1;\n    }\n\n    function authParams(address p1, bool p2) internal pure returns (uint256[] memory r) {\n        r = new uint256[](2);\n        r[0] = uint256(uint160(p1));\n        r[1] = p2 ? 1 : 0;\n    }\n\n    function authParams(address p1, uint256 p2) internal pure returns (uint256[] memory r) {\n        r = new uint256[](2);\n        r[0] = uint256(uint160(p1));\n        r[1] = p2;\n    }\n\n    function authParams(address p1, address p2) internal pure returns (uint256[] memory r) {\n        r = new uint256[](2);\n        r[0] = uint256(uint160(p1));\n        r[1] = uint256(uint160(p2));\n    }\n\n    function authParams(bytes32 p1, bytes32 p2) internal pure returns (uint256[] memory r) {\n        r = new uint256[](2);\n        r[0] = uint256(p1);\n        r[1] = uint256(p2);\n    }\n\n    function authParams(address p1, address p2, uint256 p3) internal pure returns (uint256[] memory r) {\n        r = new uint256[](3);\n        r[0] = uint256(uint160(p1));\n        r[1] = uint256(uint160(p2));\n        r[2] = p3;\n    }\n\n    function authParams(address p1, address p2, address p3) internal pure returns (uint256[] memory r) {\n        r = new uint256[](3);\n        r[0] = uint256(uint160(p1));\n        r[1] = uint256(uint160(p2));\n        r[2] = uint256(uint160(p3));\n    }\n\n    function authParams(address p1, address p2, bytes4 p3) internal pure returns (uint256[] memory r) {\n        r = new uint256[](3);\n        r[0] = uint256(uint160(p1));\n        r[1] = uint256(uint160(p2));\n        r[2] = uint256(uint32(p3));\n    }\n\n    function authParams(address p1, uint256 p2, uint256 p3) internal pure returns (uint256[] memory r) {\n        r = new uint256[](3);\n        r[0] = uint256(uint160(p1));\n        r[1] = p2;\n        r[2] = p3;\n    }\n\n    function authParams(uint256 p1, uint256 p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {\n        r = new uint256[](4);\n        r[0] = p1;\n        r[1] = p2;\n        r[2] = p3;\n        r[3] = p4;\n    }\n\n    function authParams(address p1, address p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {\n        r = new uint256[](4);\n        r[0] = uint256(uint160(p1));\n        r[1] = uint256(uint160(p2));\n        r[2] = p3;\n        r[3] = p4;\n    }\n\n    function authParams(address p1, uint256 p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {\n        r = new uint256[](4);\n        r[0] = uint256(uint160(p1));\n        r[1] = p2;\n        r[2] = p3;\n        r[3] = p4;\n    }\n\n    function authParams(bytes32 p1, address p2, uint256 p3, bool p4) internal pure returns (uint256[] memory r) {\n        r = new uint256[](4);\n        r[0] = uint256(p1);\n        r[1] = uint256(uint160(p2));\n        r[2] = p3;\n        r[3] = p4 ? 1 : 0;\n    }\n\n    function authParams(address p1, uint256 p2, uint256 p3, uint256 p4, uint256 p5)\n        internal\n        pure\n        returns (uint256[] memory r)\n    {\n        r = new uint256[](5);\n        r[0] = uint256(uint160(p1));\n        r[1] = p2;\n        r[2] = p3;\n        r[3] = p4;\n        r[4] = p5;\n    }\n}\n"
      },
      "@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorized.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\n/**\n * @dev Authorized interface\n */\ninterface IAuthorized {\n    /**\n     * @dev Sender `who` is not allowed to call `what` with `how`\n     */\n    error AuthSenderNotAllowed(address who, bytes4 what, uint256[] how);\n\n    /**\n     * @dev Tells the address of the authorizer reference\n     */\n    function authorizer() external view returns (address);\n}\n"
      },
      "@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorizer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\n/**\n * @dev Authorizer interface\n */\ninterface IAuthorizer {\n    /**\n     * @dev Permission change\n     * @param where Address of the contract to change a permission for\n     * @param changes List of permission changes to be executed\n     */\n    struct PermissionChange {\n        address where;\n        GrantPermission[] grants;\n        RevokePermission[] revokes;\n    }\n\n    /**\n     * @dev Grant permission data\n     * @param who Address to be authorized\n     * @param what Function selector to be authorized\n     * @param params List of params to restrict the given permission\n     */\n    struct GrantPermission {\n        address who;\n        bytes4 what;\n        Param[] params;\n    }\n\n    /**\n     * @dev Revoke permission data\n     * @param who Address to be unauthorized\n     * @param what Function selector to be unauthorized\n     */\n    struct RevokePermission {\n        address who;\n        bytes4 what;\n    }\n\n    /**\n     * @dev Params used to validate permissions params against\n     * @param op ID of the operation to compute in order to validate a permission param\n     * @param value Comparison value\n     */\n    struct Param {\n        uint8 op;\n        uint248 value;\n    }\n\n    /**\n     * @dev Sender is not authorized to call `what` on `where` with `how`\n     */\n    error AuthorizerSenderNotAllowed(address who, address where, bytes4 what, uint256[] how);\n\n    /**\n     * @dev The operation param is invalid\n     */\n    error AuthorizerInvalidParamOp(uint8 op);\n\n    /**\n     * @dev Emitted every time `who`'s permission to perform `what` on `where` is granted with `params`\n     */\n    event Authorized(address indexed who, address indexed where, bytes4 indexed what, Param[] params);\n\n    /**\n     * @dev Emitted every time `who`'s permission to perform `what` on `where` is revoked\n     */\n    event Unauthorized(address indexed who, address indexed where, bytes4 indexed what);\n\n    /**\n     * @dev Tells whether `who` has any permission on `where`\n     * @param who Address asking permission for\n     * @param where Target address asking permission for\n     */\n    function hasPermissions(address who, address where) external view returns (bool);\n\n    /**\n     * @dev Tells the number of permissions `who` has on `where`\n     * @param who Address asking permission for\n     * @param where Target address asking permission for\n     */\n    function getPermissionsLength(address who, address where) external view returns (uint256);\n\n    /**\n     * @dev Tells whether `who` has permission to call `what` on `where`. Note `how` is not evaluated here,\n     * which means `who` might be authorized on or not depending on the call at the moment of the execution\n     * @param who Address asking permission for\n     * @param where Target address asking permission for\n     * @param what Function selector asking permission for\n     */\n    function hasPermission(address who, address where, bytes4 what) external view returns (bool);\n\n    /**\n     * @dev Tells whether `who` is allowed to call `what` on `where` with `how`\n     * @param who Address asking permission for\n     * @param where Target address asking permission for\n     * @param what Function selector asking permission for\n     * @param how Params asking permission for\n     */\n    function isAuthorized(address who, address where, bytes4 what, uint256[] memory how) external view returns (bool);\n\n    /**\n     * @dev Tells the params set for a given permission\n     * @param who Address asking permission params of\n     * @param where Target address asking permission params of\n     * @param what Function selector asking permission params of\n     */\n    function getPermissionParams(address who, address where, bytes4 what) external view returns (Param[] memory);\n\n    /**\n     * @dev Executes a list of permission changes\n     * @param changes List of permission changes to be executed\n     */\n    function changePermissions(PermissionChange[] memory changes) external;\n\n    /**\n     * @dev Authorizes `who` to call `what` on `where` restricted by `params`\n     * @param who Address to be authorized\n     * @param where Target address to be granted for\n     * @param what Function selector to be granted\n     * @param params Optional params to restrict a permission attempt\n     */\n    function authorize(address who, address where, bytes4 what, Param[] memory params) external;\n\n    /**\n     * @dev Unauthorizes `who` to call `what` on `where`. Sender must be authorized.\n     * @param who Address to be authorized\n     * @param where Target address to be revoked for\n     * @param what Function selector to be revoked\n     */\n    function unauthorize(address who, address where, bytes4 what) external;\n}\n"
      },
      "@mimic-fi/v3-fee-controller/contracts/interfaces/IFeeController.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\n/**\n * @dev Fee controller interface\n */\ninterface IFeeController {\n    /**\n     * @dev The collector to be set is zero\n     */\n    error FeeControllerCollectorZero();\n\n    /**\n     * @dev The requested max percentage to be set is zero\n     */\n    error FeeControllerMaxPctZero();\n\n    /**\n     * @dev The requested max percentage to be set is above one\n     */\n    error FeeControllerMaxPctAboveOne();\n\n    /**\n     * @dev No max percentage has been set for the requested smart vault\n     */\n    error FeeControllerMaxPctNotSet(address smartVault);\n\n    /**\n     * @dev The requested percentage to be set is above the smart vault's max percentage\n     */\n    error FeeControllerPctAboveMax(address smartVault, uint256 pct, uint256 maxPct);\n\n    /**\n     * @dev The requested max percentage to be set is above the previous max percentage set\n     */\n    error FeeControllerMaxPctAbovePrevious(address smartVault, uint256 requestedMaxPct, uint256 previousMaxPct);\n\n    /**\n     * @dev Emitted every time a default fee collector is set\n     */\n    event DefaultFeeCollectorSet(address indexed collector);\n\n    /**\n     * @dev Emitted every time a max fee percentage is set for a smart vault\n     */\n    event MaxFeePercentageSet(address indexed smartVault, uint256 maxPct);\n\n    /**\n     * @dev Emitted every time a custom fee percentage is set\n     */\n    event FeePercentageSet(address indexed smartVault, uint256 pct);\n\n    /**\n     * @dev Emitted every time a custom fee collector is set\n     */\n    event FeeCollectorSet(address indexed smartVault, address indexed collector);\n\n    /**\n     * @dev Tells the default fee collector\n     */\n    function defaultFeeCollector() external view returns (address);\n\n    /**\n     * @dev Tells if there is a fee set for a smart vault\n     * @param smartVault Address of the smart vault being queried\n     */\n    function hasFee(address smartVault) external view returns (bool);\n\n    /**\n     * @dev Tells the applicable fee information for a smart vault\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getFee(address smartVault) external view returns (uint256 max, uint256 pct, address collector);\n\n    /**\n     * @dev Sets the default fee collector\n     * @param collector Default fee collector to be set\n     */\n    function setDefaultFeeCollector(address collector) external;\n\n    /**\n     * @dev Sets a max fee percentage for a smart vault\n     * @param smartVault Address of smart vault to set a fee percentage for\n     * @param maxPct Max fee percentage to be set\n     */\n    function setMaxFeePercentage(address smartVault, uint256 maxPct) external;\n\n    /**\n     * @dev Sets a fee percentage for a smart vault\n     * @param smartVault Address of smart vault to set a fee percentage for\n     * @param pct Fee percentage to be set\n     */\n    function setFeePercentage(address smartVault, uint256 pct) external;\n\n    /**\n     * @dev Sets a fee collector for a smart vault\n     * @param smartVault Address of smart vault to set a fee collector for\n     * @param collector Fee collector to be set\n     */\n    function setFeeCollector(address smartVault, address collector) external;\n}\n"
      },
      "@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\n/**\n * @title FixedPoint\n * @dev Math library to operate with fixed point values with 18 decimals\n */\nlibrary FixedPoint {\n    // 1 in fixed point value: 18 decimal places\n    uint256 internal constant ONE = 1e18;\n\n    /**\n     * @dev Multiplication overflow\n     */\n    error FixedPointMulOverflow(uint256 a, uint256 b);\n\n    /**\n     * @dev Division by zero\n     */\n    error FixedPointZeroDivision();\n\n    /**\n     * @dev Division internal error\n     */\n    error FixedPointDivInternal(uint256 a, uint256 aInflated);\n\n    /**\n     * @dev Multiplies two fixed point numbers rounding down\n     */\n    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            uint256 product = a * b;\n            if (a != 0 && product / a != b) revert FixedPointMulOverflow(a, b);\n            return product / ONE;\n        }\n    }\n\n    /**\n     * @dev Multiplies two fixed point numbers rounding up\n     */\n    function mulUp(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            uint256 product = a * b;\n            if (a != 0 && product / a != b) revert FixedPointMulOverflow(a, b);\n            return product == 0 ? 0 : (((product - 1) / ONE) + 1);\n        }\n    }\n\n    /**\n     * @dev Divides two fixed point numbers rounding down\n     */\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            if (b == 0) revert FixedPointZeroDivision();\n            if (a == 0) return 0;\n            uint256 aInflated = a * ONE;\n            if (aInflated / a != ONE) revert FixedPointDivInternal(a, aInflated);\n            return aInflated / b;\n        }\n    }\n\n    /**\n     * @dev Divides two fixed point numbers rounding up\n     */\n    function divUp(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            if (b == 0) revert FixedPointZeroDivision();\n            if (a == 0) return 0;\n            uint256 aInflated = a * ONE;\n            if (aInflated / a != ONE) revert FixedPointDivInternal(a, aInflated);\n            return ((aInflated - 1) / b) + 1;\n        }\n    }\n}\n"
      },
      "@mimic-fi/v3-helpers/contracts/utils/Denominations.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\n/**\n * @title Denominations\n * @dev Provides a list of ground denominations for those tokens that cannot be represented by an ERC20.\n * For now, the only needed is the native token that could be ETH, MATIC, or other depending on the layer being operated.\n */\nlibrary Denominations {\n    address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217\n    address internal constant USD = address(840);\n\n    function isNativeToken(address token) internal pure returns (bool) {\n        return token == NATIVE_TOKEN;\n    }\n}\n"
      },
      "@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nimport './Denominations.sol';\n\n/**\n * @title ERC20Helpers\n * @dev Provides a list of ERC20 helper methods\n */\nlibrary ERC20Helpers {\n    function approve(address token, address to, uint256 amount) internal {\n        SafeERC20.forceApprove(IERC20(token), to, amount);\n    }\n\n    function transfer(address token, address to, uint256 amount) internal {\n        if (Denominations.isNativeToken(token)) Address.sendValue(payable(to), amount);\n        else SafeERC20.safeTransfer(IERC20(token), to, amount);\n    }\n\n    function balanceOf(address token, address account) internal view returns (uint256) {\n        if (Denominations.isNativeToken(token)) return address(account).balance;\n        else return IERC20(token).balanceOf(address(account));\n    }\n}\n"
      },
      "@mimic-fi/v3-price-oracle/contracts/interfaces/IPriceOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorized.sol';\n\n/**\n * @title IPriceOracle\n * @dev Price oracle interface\n *\n * Tells the price of a token (base) in a given quote based the following rule: the response is expressed using the\n * corresponding number of decimals so that when performing a fixed point product of it by a `base` amount it results\n * in a value expressed in `quote` decimals. For example, if `base` is ETH and `quote` is USDC, then the returned\n * value is expected to be expressed using 6 decimals:\n *\n * FixedPoint.mul(X[ETH], price[USDC/ETH]) = FixedPoint.mul(X[18], price[6]) = X * price [6]\n */\ninterface IPriceOracle is IAuthorized {\n    /**\n     * @dev Price data\n     * @param base Token to rate\n     * @param quote Token used for the price rate\n     * @param rate Price of a token (base) expressed in `quote`\n     * @param deadline Expiration timestamp until when the given quote is considered valid\n     */\n    struct PriceData {\n        address base;\n        address quote;\n        uint256 rate;\n        uint256 deadline;\n    }\n\n    /**\n     * @dev The signer is not allowed\n     */\n    error PriceOracleInvalidSigner(address signer);\n\n    /**\n     * @dev The feed for the given (base, quote) pair doesn't exist\n     */\n    error PriceOracleMissingFeed(address base, address quote);\n\n    /**\n     * @dev The price deadline is in the past\n     */\n    error PriceOracleOutdatedPrice(address base, address quote, uint256 deadline, uint256 currentTimestamp);\n\n    /**\n     * @dev The base decimals are bigger than the quote decimals plus the fixed point decimals\n     */\n    error PriceOracleBaseDecimalsTooBig(address base, uint256 baseDecimals, address quote, uint256 quoteDecimals);\n\n    /**\n     * @dev The inverse feed decimals are bigger than the maximum inverse feed decimals\n     */\n    error PriceOracleInverseFeedDecimalsTooBig(address inverseFeed, uint256 inverseFeedDecimals);\n\n    /**\n     * @dev The quote feed decimals are bigger than the base feed decimals plus the fixed point decimals\n     */\n    error PriceOracleQuoteFeedDecimalsTooBig(uint256 quoteFeedDecimals, uint256 baseFeedDecimals);\n\n    /**\n     * @dev Emitted every time a signer is changed\n     */\n    event SignerSet(address indexed signer, bool allowed);\n\n    /**\n     * @dev Emitted every time a feed is set for (base, quote) pair\n     */\n    event FeedSet(address indexed base, address indexed quote, address feed);\n\n    /**\n     * @dev Tells whether an address is as an allowed signer or not\n     * @param signer Address of the signer being queried\n     */\n    function isSignerAllowed(address signer) external view returns (bool);\n\n    /**\n     * @dev Tells the list of allowed signers\n     */\n    function getAllowedSigners() external view returns (address[] memory);\n\n    /**\n     * @dev Tells the digest expected to be signed by the off-chain oracle signers for a list of prices\n     * @param prices List of prices to be signed\n     */\n    function getPricesDigest(PriceData[] memory prices) external view returns (bytes32);\n\n    /**\n     * @dev Tells the price of a token `base` expressed in a token `quote`\n     * @param base Token to rate\n     * @param quote Token used for the price rate\n     */\n    function getPrice(address base, address quote) external view returns (uint256);\n\n    /**\n     * @dev Tells the price of a token `base` expressed in a token `quote`\n     * @param base Token to rate\n     * @param quote Token used for the price rate\n     * @param data Encoded data to validate in order to compute the requested rate\n     */\n    function getPrice(address base, address quote, bytes memory data) external view returns (uint256);\n\n    /**\n     * @dev Tells the feed address for (base, quote) pair. It returns the zero address if there is no one set.\n     * @param base Token to be rated\n     * @param quote Token used for the price rate\n     */\n    function getFeed(address base, address quote) external view returns (address);\n\n    /**\n     * @dev Sets a signer condition\n     * @param signer Address of the signer to be set\n     * @param allowed Whether the requested signer is allowed\n     */\n    function setSigner(address signer, bool allowed) external;\n\n    /**\n     * @dev Sets a feed for a (base, quote) pair\n     * @param base Token base to be set\n     * @param quote Token quote to be set\n     * @param feed Feed to be set\n     */\n    function setFeed(address base, address quote, address feed) external;\n}\n"
      },
      "@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorized.sol';\n\n/**\n * @dev Smart Vault interface\n */\ninterface ISmartVault is IAuthorized {\n    /**\n     * @dev The smart vault is paused\n     */\n    error SmartVaultPaused();\n\n    /**\n     * @dev The smart vault is unpaused\n     */\n    error SmartVaultUnpaused();\n\n    /**\n     * @dev The token is zero\n     */\n    error SmartVaultTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error SmartVaultAmountZero();\n\n    /**\n     * @dev The recipient is zero\n     */\n    error SmartVaultRecipientZero();\n\n    /**\n     * @dev The connector is deprecated\n     */\n    error SmartVaultConnectorDeprecated(address connector);\n\n    /**\n     * @dev The connector is not registered\n     */\n    error SmartVaultConnectorNotRegistered(address connector);\n\n    /**\n     * @dev The connector is not stateless\n     */\n    error SmartVaultConnectorNotStateless(address connector);\n\n    /**\n     * @dev The connector ID is zero\n     */\n    error SmartVaultBalanceConnectorIdZero();\n\n    /**\n     * @dev The balance connector's balance is lower than the requested amount to be deducted\n     */\n    error SmartVaultBalanceConnectorInsufficientBalance(bytes32 id, address token, uint256 balance, uint256 amount);\n\n    /**\n     * @dev The smart vault's native token balance is lower than the requested amount to be deducted\n     */\n    error SmartVaultInsufficientNativeTokenBalance(uint256 balance, uint256 amount);\n\n    /**\n     * @dev Emitted every time a smart vault is paused\n     */\n    event Paused();\n\n    /**\n     * @dev Emitted every time a smart vault is unpaused\n     */\n    event Unpaused();\n\n    /**\n     * @dev Emitted every time the price oracle is set\n     */\n    event PriceOracleSet(address indexed priceOracle);\n\n    /**\n     * @dev Emitted every time a connector check is overridden\n     */\n    event ConnectorCheckOverridden(address indexed connector, bool ignored);\n\n    /**\n     * @dev Emitted every time a balance connector is updated\n     */\n    event BalanceConnectorUpdated(bytes32 indexed id, address indexed token, uint256 amount, bool added);\n\n    /**\n     * @dev Emitted every time `execute` is called\n     */\n    event Executed(address indexed connector, bytes data, bytes result);\n\n    /**\n     * @dev Emitted every time `call` is called\n     */\n    event Called(address indexed target, bytes data, uint256 value, bytes result);\n\n    /**\n     * @dev Emitted every time `wrap` is called\n     */\n    event Wrapped(uint256 amount);\n\n    /**\n     * @dev Emitted every time `unwrap` is called\n     */\n    event Unwrapped(uint256 amount);\n\n    /**\n     * @dev Emitted every time `collect` is called\n     */\n    event Collected(address indexed token, address indexed from, uint256 amount);\n\n    /**\n     * @dev Emitted every time `withdraw` is called\n     */\n    event Withdrawn(address indexed token, address indexed recipient, uint256 amount, uint256 fee);\n\n    /**\n     * @dev Tells if the smart vault is paused or not\n     */\n    function isPaused() external view returns (bool);\n\n    /**\n     * @dev Tells the address of the price oracle\n     */\n    function priceOracle() external view returns (address);\n\n    /**\n     * @dev Tells the address of the Mimic's registry\n     */\n    function registry() external view returns (address);\n\n    /**\n     * @dev Tells the address of the Mimic's fee controller\n     */\n    function feeController() external view returns (address);\n\n    /**\n     * @dev Tells the address of the wrapped native token\n     */\n    function wrappedNativeToken() external view returns (address);\n\n    /**\n     * @dev Tells if a connector check is ignored\n     * @param connector Address of the connector being queried\n     */\n    function isConnectorCheckIgnored(address connector) external view returns (bool);\n\n    /**\n     * @dev Tells the balance to a balance connector for a token\n     * @param id Balance connector identifier\n     * @param token Address of the token querying the balance connector for\n     */\n    function getBalanceConnector(bytes32 id, address token) external view returns (uint256);\n\n    /**\n     * @dev Tells whether someone has any permission over the smart vault\n     */\n    function hasPermissions(address who) external view returns (bool);\n\n    /**\n     * @dev Pauses a smart vault\n     */\n    function pause() external;\n\n    /**\n     * @dev Unpauses a smart vault\n     */\n    function unpause() external;\n\n    /**\n     * @dev Sets the price oracle\n     * @param newPriceOracle Address of the new price oracle to be set\n     */\n    function setPriceOracle(address newPriceOracle) external;\n\n    /**\n     * @dev Overrides connector checks\n     * @param connector Address of the connector to override its check\n     * @param ignored Whether the connector check should be ignored\n     */\n    function overrideConnectorCheck(address connector, bool ignored) external;\n\n    /**\n     * @dev Updates a balance connector\n     * @param id Balance connector identifier to be updated\n     * @param token Address of the token to update the balance connector for\n     * @param amount Amount to be updated to the balance connector\n     * @param add Whether the balance connector should be increased or decreased\n     */\n    function updateBalanceConnector(bytes32 id, address token, uint256 amount, bool add) external;\n\n    /**\n     * @dev Executes a connector inside of the Smart Vault context\n     * @param connector Address of the connector that will be executed\n     * @param data Call data to be used for the delegate-call\n     * @return result Call response if it was successful, otherwise it reverts\n     */\n    function execute(address connector, bytes memory data) external returns (bytes memory result);\n\n    /**\n     * @dev Executes an arbitrary call from the Smart Vault\n     * @param target Address where the call will be sent\n     * @param data Call data to be used for the call\n     * @param value Value in wei that will be attached to the call\n     * @return result Call response if it was successful, otherwise it reverts\n     */\n    function call(address target, bytes memory data, uint256 value) external returns (bytes memory result);\n\n    /**\n     * @dev Wrap an amount of native tokens to the wrapped ERC20 version of it\n     * @param amount Amount of native tokens to be wrapped\n     */\n    function wrap(uint256 amount) external;\n\n    /**\n     * @dev Unwrap an amount of wrapped native tokens\n     * @param amount Amount of wrapped native tokens to unwrapped\n     */\n    function unwrap(uint256 amount) external;\n\n    /**\n     * @dev Collect tokens from an external account to the Smart Vault\n     * @param token Address of the token to be collected\n     * @param from Address where the tokens will be transferred from\n     * @param amount Amount of tokens to be transferred\n     */\n    function collect(address token, address from, uint256 amount) external;\n\n    /**\n     * @dev Withdraw tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param recipient Address where the tokens will be transferred to\n     * @param amount Amount of tokens to withdraw\n     */\n    function withdraw(address token, address recipient, uint256 amount) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/BaseTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\nimport '@mimic-fi/v3-helpers/contracts/utils/Denominations.sol';\nimport '@mimic-fi/v3-price-oracle/contracts/interfaces/IPriceOracle.sol';\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\n\nimport '../interfaces/base/IBaseTask.sol';\n\n/**\n * @title BaseTask\n * @dev Base task implementation with a Smart Vault reference and using the Authorizer\n */\nabstract contract BaseTask is IBaseTask, Authorized {\n    // Smart Vault reference\n    address public override smartVault;\n\n    // Optional balance connector id for the previous task in the workflow\n    bytes32 internal previousBalanceConnectorId;\n\n    // Optional balance connector id for the next task in the workflow\n    bytes32 internal nextBalanceConnectorId;\n\n    /**\n     * @dev Base task config. Only used in the initializer.\n     * @param smartVault Address of the smart vault this task will reference, it cannot be changed once set\n     * @param previousBalanceConnectorId Balance connector id for the previous task in the workflow\n     * @param nextBalanceConnectorId Balance connector id for the next task in the workflow\n     */\n    struct BaseConfig {\n        address smartVault;\n        bytes32 previousBalanceConnectorId;\n        bytes32 nextBalanceConnectorId;\n    }\n\n    /**\n     * @dev Initializes the base task. It does call upper contracts initializers.\n     * @param config Base task config\n     */\n    function __BaseTask_init(BaseConfig memory config) internal onlyInitializing {\n        __Authorized_init(ISmartVault(config.smartVault).authorizer());\n        __BaseTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the base task. It does not call upper contracts initializers.\n     * @param config Base task config\n     */\n    function __BaseTask_init_unchained(BaseConfig memory config) internal onlyInitializing {\n        smartVault = config.smartVault;\n        _setBalanceConnectors(config.previousBalanceConnectorId, config.nextBalanceConnectorId);\n    }\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched.\n     * Since by default tasks are supposed to use balance connectors, the tokens source has to be the smart vault.\n     * In case a task does not need to rely on a previous balance connector, it must override this function to specify\n     * where it is getting its tokens from.\n     */\n    function getTokensSource() external view virtual override returns (address) {\n        return smartVault;\n    }\n\n    /**\n     * @dev Tells the amount a task should use for a token. By default tasks are expected to use balance connectors.\n     * In case a task relies on an external tokens source, it must override how the task amount is calculated.\n     * @param token Address of the token being queried\n     */\n    function getTaskAmount(address token) public view virtual override returns (uint256) {\n        return ISmartVault(smartVault).getBalanceConnector(previousBalanceConnectorId, token);\n    }\n\n    /**\n     * @dev Tells the previous and next balance connectors id of the previous task in the workflow\n     */\n    function getBalanceConnectors() external view returns (bytes32 previous, bytes32 next) {\n        previous = previousBalanceConnectorId;\n        next = nextBalanceConnectorId;\n    }\n\n    /**\n     * @dev Sets the balance connectors\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function setBalanceConnectors(bytes32 previous, bytes32 next) external override authP(authParams(previous, next)) {\n        _setBalanceConnectors(previous, next);\n    }\n\n    /**\n     * @dev Tells the wrapped native token address if the given address is the native token\n     * @param token Address of the token to be checked\n     */\n    function _wrappedIfNative(address token) internal view returns (address) {\n        return Denominations.isNativeToken(token) ? _wrappedNativeToken() : token;\n    }\n\n    /**\n     * @dev Tells whether a token is the native or the wrapped native token\n     * @param token Address of the token to be checked\n     */\n    function _isWrappedOrNative(address token) internal view returns (bool) {\n        return Denominations.isNativeToken(token) || token == _wrappedNativeToken();\n    }\n\n    /**\n     * @dev Tells the wrapped native token address\n     */\n    function _wrappedNativeToken() internal view returns (address) {\n        return ISmartVault(smartVault).wrappedNativeToken();\n    }\n\n    /**\n     * @dev Fetches a base/quote price from the smart vault's price oracle\n     * @param base Token to rate\n     * @param quote Token used for the price rate\n     */\n    function _getPrice(address base, address quote) internal view virtual returns (uint256) {\n        address priceOracle = ISmartVault(smartVault).priceOracle();\n        if (priceOracle == address(0)) revert TaskSmartVaultPriceOracleNotSet(smartVault);\n        bytes memory extraCallData = _decodeExtraCallData();\n        return\n            extraCallData.length == 0\n                ? IPriceOracle(priceOracle).getPrice(_wrappedIfNative(base), _wrappedIfNative(quote))\n                : IPriceOracle(priceOracle).getPrice(_wrappedIfNative(base), _wrappedIfNative(quote), extraCallData);\n    }\n\n    /**\n     * @dev Before base task hook\n     */\n    function _beforeBaseTask(address token, uint256 amount) internal virtual {\n        _decreaseBalanceConnector(token, amount);\n    }\n\n    /**\n     * @dev After base task hook\n     */\n    function _afterBaseTask(address, uint256) internal virtual {\n        emit Executed();\n    }\n\n    /**\n     * @dev Decreases the previous balance connector in the smart vault if defined\n     * @param token Address of the token to update the previous balance connector of\n     * @param amount Amount to be updated\n     */\n    function _decreaseBalanceConnector(address token, uint256 amount) internal {\n        if (previousBalanceConnectorId != bytes32(0)) {\n            ISmartVault(smartVault).updateBalanceConnector(previousBalanceConnectorId, token, amount, false);\n        }\n    }\n\n    /**\n     * @dev Increases the next balance connector in the smart vault if defined\n     * @param token Address of the token to update the next balance connector of\n     * @param amount Amount to be updated\n     */\n    function _increaseBalanceConnector(address token, uint256 amount) internal {\n        if (nextBalanceConnectorId != bytes32(0)) {\n            ISmartVault(smartVault).updateBalanceConnector(nextBalanceConnectorId, token, amount, true);\n        }\n    }\n\n    /**\n     * @dev Sets the balance connectors\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function _setBalanceConnectors(bytes32 previous, bytes32 next) internal virtual {\n        if (previous == next && previous != bytes32(0)) revert TaskSameBalanceConnectors(previous);\n        previousBalanceConnectorId = previous;\n        nextBalanceConnectorId = next;\n        emit BalanceConnectorsSet(previous, next);\n    }\n\n    /**\n     * @dev Decodes any potential extra calldata stored in the calldata space. Tasks relying on the extra calldata\n     * pattern, assume that the last word of the calldata stores the extra calldata length so it can be decoded. Note\n     * that tasks relying on this pattern must contemplate this function may return bogus data if no extra calldata\n     * was given.\n     */\n    function _decodeExtraCallData() private pure returns (bytes memory data) {\n        uint256 length = uint256(_decodeLastCallDataWord());\n        if (msg.data.length < length) return new bytes(0);\n        data = new bytes(length);\n        assembly {\n            calldatacopy(add(data, 0x20), sub(sub(calldatasize(), length), 0x20), length)\n        }\n    }\n\n    /**\n     * @dev Returns the last calldata word. This function returns zero if the calldata is not long enough.\n     */\n    function _decodeLastCallDataWord() private pure returns (bytes32 result) {\n        if (msg.data.length < 36) return bytes32(0);\n        assembly {\n            result := calldataload(sub(calldatasize(), 0x20))\n        }\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/GasLimitedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\n\nimport '../interfaces/base/IGasLimitedTask.sol';\n\n/**\n * @dev Gas config for tasks. It allows setting different gas-related configs, specially useful to control relayed txs.\n */\nabstract contract GasLimitedTask is IGasLimitedTask, Authorized {\n    using FixedPoint for uint256;\n\n    // Variable used to allow a better developer experience to reimburse tx gas cost\n    // solhint-disable-next-line var-name-mixedcase\n    uint256 private __initialGas__;\n\n    // Gas limits config\n    GasLimitConfig internal gasLimits;\n\n    /**\n     * @dev Gas limits config\n     * @param gasPriceLimit Gas price limit expressed in the native token\n     * @param priorityFeeLimit Priority fee limit expressed in the native token\n     * @param txCostLimit Transaction cost limit to be set\n     * @param txCostLimitPct Transaction cost limit percentage to be set\n     */\n    struct GasLimitConfig {\n        uint256 gasPriceLimit;\n        uint256 priorityFeeLimit;\n        uint256 txCostLimit;\n        uint256 txCostLimitPct;\n    }\n\n    /**\n     * @dev Initializes the gas limited task. It does call upper contracts initializers.\n     * @param config Gas limited task config\n     */\n    function __GasLimitedTask_init(GasLimitConfig memory config) internal onlyInitializing {\n        __GasLimitedTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the gas limited task. It does not call upper contracts initializers.\n     * @param config Gas limited task config\n     */\n    function __GasLimitedTask_init_unchained(GasLimitConfig memory config) internal onlyInitializing {\n        _setGasLimits(config.gasPriceLimit, config.priorityFeeLimit, config.txCostLimit, config.txCostLimitPct);\n    }\n\n    /**\n     * @dev Tells the gas limits config\n     */\n    function getGasLimits()\n        external\n        view\n        returns (uint256 gasPriceLimit, uint256 priorityFeeLimit, uint256 txCostLimit, uint256 txCostLimitPct)\n    {\n        return (gasLimits.gasPriceLimit, gasLimits.priorityFeeLimit, gasLimits.txCostLimit, gasLimits.txCostLimitPct);\n    }\n\n    /**\n     * @dev Sets the gas limits config\n     * @param newGasPriceLimit New gas price limit to be set\n     * @param newPriorityFeeLimit New priority fee limit to be set\n     * @param newTxCostLimit New tx cost limit to be set\n     * @param newTxCostLimitPct New tx cost percentage limit to be set\n     */\n    function setGasLimits(\n        uint256 newGasPriceLimit,\n        uint256 newPriorityFeeLimit,\n        uint256 newTxCostLimit,\n        uint256 newTxCostLimitPct\n    ) external override authP(authParams(newGasPriceLimit, newPriorityFeeLimit, newTxCostLimit, newTxCostLimitPct)) {\n        _setGasLimits(newGasPriceLimit, newPriorityFeeLimit, newTxCostLimit, newTxCostLimitPct);\n    }\n\n    /**\n     * @dev Fetches a base/quote price\n     */\n    function _getPrice(address base, address quote) internal view virtual returns (uint256);\n\n    /**\n     * @dev Initializes gas limited tasks and validates gas price limit\n     */\n    function _beforeGasLimitedTask(address, uint256) internal virtual {\n        __initialGas__ = gasleft();\n        GasLimitConfig memory config = gasLimits;\n        bool isGasPriceAllowed = config.gasPriceLimit == 0 || tx.gasprice <= config.gasPriceLimit;\n        if (!isGasPriceAllowed) revert TaskGasPriceLimitExceeded(tx.gasprice, config.gasPriceLimit);\n\n        if (config.priorityFeeLimit > 0) {\n            uint256 priorityFee = tx.gasprice - block.basefee;\n            bool isPriorityFeeAllowed = priorityFee <= config.priorityFeeLimit;\n            if (!isPriorityFeeAllowed) revert TaskPriorityFeeLimitExceeded(priorityFee, config.priorityFeeLimit);\n        }\n    }\n\n    /**\n     * @dev Validates transaction cost limit\n     */\n    function _afterGasLimitedTask(address token, uint256 amount) internal virtual {\n        if (__initialGas__ == 0) revert TaskGasNotInitialized();\n\n        GasLimitConfig memory config = gasLimits;\n        uint256 totalGas = __initialGas__ - gasleft();\n        uint256 totalCost = totalGas * tx.gasprice;\n        bool isTxCostAllowed = config.txCostLimit == 0 || totalCost <= config.txCostLimit;\n        if (!isTxCostAllowed) revert TaskTxCostLimitExceeded(totalCost, config.txCostLimit);\n        delete __initialGas__;\n\n        if (config.txCostLimitPct > 0 && amount > 0) {\n            uint256 price = _getPrice(ISmartVault(this.smartVault()).wrappedNativeToken(), token);\n            uint256 totalCostInToken = totalCost.mulUp(price);\n            uint256 txCostPct = totalCostInToken.divUp(amount);\n            if (txCostPct > config.txCostLimitPct) revert TaskTxCostLimitPctExceeded(txCostPct, config.txCostLimitPct);\n        }\n    }\n\n    /**\n     * @dev Sets the gas limits config\n     * @param newGasPriceLimit New gas price limit to be set\n     * @param newPriorityFeeLimit New priority fee limit to be set\n     * @param newTxCostLimit New tx cost limit to be set\n     * @param newTxCostLimitPct New tx cost percentage limit to be set\n     */\n    function _setGasLimits(\n        uint256 newGasPriceLimit,\n        uint256 newPriorityFeeLimit,\n        uint256 newTxCostLimit,\n        uint256 newTxCostLimitPct\n    ) internal {\n        if (newTxCostLimitPct > FixedPoint.ONE) revert TaskTxCostLimitPctAboveOne();\n\n        gasLimits.gasPriceLimit = newGasPriceLimit;\n        gasLimits.priorityFeeLimit = newPriorityFeeLimit;\n        gasLimits.txCostLimit = newTxCostLimit;\n        gasLimits.txCostLimitPct = newTxCostLimitPct;\n        emit GasLimitsSet(newGasPriceLimit, newPriorityFeeLimit, newTxCostLimit, newTxCostLimitPct);\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/PausableTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\n\nimport '../interfaces/base/IPausableTask.sol';\n\n/**\n * @dev Pausable config for tasks\n */\nabstract contract PausableTask is IPausableTask, Authorized {\n    using FixedPoint for uint256;\n\n    // Whether the task is paused or not\n    bool public override isPaused;\n\n    /**\n     * @dev Initializes the pausable task. It does call upper contracts initializers.\n     */\n    function __PausableTask_init() internal onlyInitializing {\n        __PausableTask_init_unchained();\n    }\n\n    /**\n     * @dev Initializes the pausable task. It does not call upper contracts initializers.\n     */\n    function __PausableTask_init_unchained() internal onlyInitializing {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Pauses a task\n     */\n    function pause() external override auth {\n        if (isPaused) revert TaskPaused();\n        isPaused = true;\n        emit Paused();\n    }\n\n    /**\n     * @dev Unpauses a task\n     */\n    function unpause() external override auth {\n        if (!isPaused) revert TaskUnpaused();\n        isPaused = false;\n        emit Unpaused();\n    }\n\n    /**\n     * @dev Before pausable task hook\n     */\n    function _beforePausableTask(address, uint256) internal virtual {\n        if (isPaused) revert TaskPaused();\n    }\n\n    /**\n     * @dev After pausable task hook\n     */\n    function _afterPausableTask(address, uint256) internal virtual {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/TimeLockedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.3;\n\nimport '@quant-finance/solidity-datetime/contracts/DateTime.sol';\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\n\nimport '../interfaces/base/ITimeLockedTask.sol';\n\n/**\n * @dev Time lock config for tasks. It allows limiting the frequency of a task.\n */\nabstract contract TimeLockedTask is ITimeLockedTask, Authorized {\n    using DateTime for uint256;\n\n    uint256 private constant DAYS_28 = 60 * 60 * 24 * 28;\n\n    /**\n     * @dev Time-locks supports different frequency modes\n     * @param Seconds To indicate the execution must occur every certain number of seconds\n     * @param OnDay To indicate the execution must occur on day number from 1 to 28 every certain months\n     * @param OnLastMonthDay To indicate the execution must occur on the last day of the month every certain months\n     */\n    enum Mode {\n        Seconds,\n        OnDay,\n        OnLastMonthDay\n    }\n\n    // Time lock mode\n    Mode internal _mode;\n\n    // Time lock frequency\n    uint256 internal _frequency;\n\n    // Future timestamp since when the task can be executed\n    uint256 internal _allowedAt;\n\n    // Next future timestamp since when the task can be executed to be set, only used internally\n    uint256 internal _nextAllowedAt;\n\n    // Period in seconds during when a time-locked task can be executed since the allowed timestamp\n    uint256 internal _window;\n\n    /**\n     * @dev Time lock config params. Only used in the initializer.\n     * @param mode Time lock mode\n     * @param frequency Time lock frequency value\n     * @param allowedAt Time lock allowed date\n     * @param window Time lock execution window\n     */\n    struct TimeLockConfig {\n        uint8 mode;\n        uint256 frequency;\n        uint256 allowedAt;\n        uint256 window;\n    }\n\n    /**\n     * @dev Initializes the time locked task. It does not call upper contracts initializers.\n     * @param config Time locked task config\n     */\n    function __TimeLockedTask_init(TimeLockConfig memory config) internal onlyInitializing {\n        __TimeLockedTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the time locked task. It does call upper contracts initializers.\n     * @param config Time locked task config\n     */\n    function __TimeLockedTask_init_unchained(TimeLockConfig memory config) internal onlyInitializing {\n        _setTimeLock(config.mode, config.frequency, config.allowedAt, config.window);\n    }\n\n    /**\n     * @dev Tells the time-lock related information\n     */\n    function getTimeLock() external view returns (uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window) {\n        return (uint8(_mode), _frequency, _allowedAt, _window);\n    }\n\n    /**\n     * @dev Sets a new time lock\n     */\n    function setTimeLock(uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window)\n        external\n        override\n        authP(authParams(mode, frequency, allowedAt, window))\n    {\n        _setTimeLock(mode, frequency, allowedAt, window);\n    }\n\n    /**\n     * @dev Before time locked task hook\n     */\n    function _beforeTimeLockedTask(address, uint256) internal virtual {\n        // Load storage variables\n        Mode mode = _mode;\n        uint256 frequency = _frequency;\n        uint256 allowedAt = _allowedAt;\n        uint256 window = _window;\n\n        // First we check the current timestamp is not in the past\n        if (block.timestamp < allowedAt) revert TaskTimeLockActive(block.timestamp, allowedAt);\n\n        if (mode == Mode.Seconds) {\n            if (frequency == 0) return;\n\n            // If no window is set, the next allowed date is simply moved the number of seconds set as frequency.\n            // Otherwise, the offset must be validated and the next allowed date is set to the next period.\n            if (window == 0) _nextAllowedAt = block.timestamp + frequency;\n            else {\n                uint256 diff = block.timestamp - allowedAt;\n                uint256 periods = diff / frequency;\n                uint256 offset = diff - (periods * frequency);\n                if (offset > window) revert TaskTimeLockActive(block.timestamp, allowedAt);\n                _nextAllowedAt = allowedAt + ((periods + 1) * frequency);\n            }\n        } else {\n            if (block.timestamp >= allowedAt && block.timestamp <= allowedAt + window) {\n                // Check the current timestamp has not passed the allowed date set\n                _nextAllowedAt = _getNextAllowedDate(allowedAt, frequency);\n            } else {\n                // Check the current timestamp is not before the current allowed date\n                uint256 currentAllowedDay = mode == Mode.OnDay ? allowedAt.getDay() : block.timestamp.getDaysInMonth();\n                uint256 currentAllowedAt = _getCurrentAllowedDate(allowedAt, currentAllowedDay);\n                if (block.timestamp < currentAllowedAt) revert TaskTimeLockActive(block.timestamp, currentAllowedAt);\n\n                // Check the current timestamp has not passed the allowed execution window\n                uint256 extendedCurrentAllowedAt = currentAllowedAt + window;\n                bool exceedsExecutionWindow = block.timestamp > extendedCurrentAllowedAt;\n                if (exceedsExecutionWindow) revert TaskTimeLockActive(block.timestamp, extendedCurrentAllowedAt);\n\n                // Finally set the next allowed date to the corresponding number of months from the current date\n                _nextAllowedAt = _getNextAllowedDate(currentAllowedAt, frequency);\n            }\n        }\n    }\n\n    /**\n     * @dev After time locked task hook\n     */\n    function _afterTimeLockedTask(address, uint256) internal virtual {\n        if (_nextAllowedAt == 0) return;\n        _setTimeLockAllowedAt(_nextAllowedAt);\n        _nextAllowedAt = 0;\n    }\n\n    /**\n     * @dev Sets a new time lock\n     */\n    function _setTimeLock(uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window) internal {\n        if (mode == uint8(Mode.Seconds)) {\n            // The execution window and timestamp are optional, but both must be given or none\n            // If given the execution window cannot be larger than the number of seconds\n            // Also, if these are given the frequency must be checked as well, otherwise it could be unsetting the lock\n            if (window > 0 || allowedAt > 0) {\n                if (frequency == 0) revert TaskInvalidFrequency(mode, frequency);\n                if (window == 0 || window > frequency) revert TaskInvalidAllowedWindow(mode, window);\n                if (allowedAt == 0) revert TaskInvalidAllowedDate(mode, allowedAt);\n            }\n        } else {\n            // The other modes can be \"on-day\" or \"on-last-day\" where the frequency represents a number of months\n            // There is no limit for the frequency, it simply cannot be zero\n            if (frequency == 0) revert TaskInvalidFrequency(mode, frequency);\n\n            // The execution window cannot be larger than the number of months considering months of 28 days\n            if (window == 0 || window > frequency * DAYS_28) revert TaskInvalidAllowedWindow(mode, window);\n\n            // The allowed date cannot be zero\n            if (allowedAt == 0) revert TaskInvalidAllowedDate(mode, allowedAt);\n\n            // If the mode is \"on-day\", the allowed date must be valid for every month, then the allowed day cannot be\n            // larger than 28. But if the mode is \"on-last-day\", the allowed date day must be the last day of the month\n            if (mode == uint8(Mode.OnDay)) {\n                if (allowedAt.getDay() > 28) revert TaskInvalidAllowedDate(mode, allowedAt);\n            } else if (mode == uint8(Mode.OnLastMonthDay)) {\n                if (allowedAt.getDay() != allowedAt.getDaysInMonth()) revert TaskInvalidAllowedDate(mode, allowedAt);\n            } else {\n                revert TaskInvalidFrequencyMode(mode);\n            }\n        }\n\n        _mode = Mode(mode);\n        _frequency = frequency;\n        _allowedAt = allowedAt;\n        _window = window;\n\n        emit TimeLockSet(mode, frequency, allowedAt, window);\n    }\n\n    /**\n     * @dev Sets the time-lock execution allowed timestamp\n     * @param allowedAt New execution allowed timestamp to be set\n     */\n    function _setTimeLockAllowedAt(uint256 allowedAt) internal {\n        _allowedAt = allowedAt;\n        emit TimeLockAllowedAtSet(allowedAt);\n    }\n\n    /**\n     * @dev Tells the corresponding allowed date based on a current timestamp\n     */\n    function _getCurrentAllowedDate(uint256 allowedAt, uint256 day) private view returns (uint256) {\n        (uint256 year, uint256 month, ) = block.timestamp.timestampToDate();\n        return _getAllowedDateFor(allowedAt, year, month, day);\n    }\n\n    /**\n     * @dev Tells the next allowed date based on a current allowed date considering a number of months to increase\n     */\n    function _getNextAllowedDate(uint256 allowedAt, uint256 monthsToIncrease) private view returns (uint256) {\n        (uint256 year, uint256 month, uint256 day) = allowedAt.timestampToDate();\n        uint256 increasedMonth = month + monthsToIncrease;\n        uint256 nextMonth = increasedMonth % 12;\n        uint256 nextYear = year + (increasedMonth / 12);\n        uint256 nextDay = _mode == Mode.OnLastMonthDay ? DateTime._getDaysInMonth(nextYear, nextMonth) : day;\n        return _getAllowedDateFor(allowedAt, nextYear, nextMonth, nextDay);\n    }\n\n    /**\n     * @dev Builds an allowed date using a specific year, month, and day\n     */\n    function _getAllowedDateFor(uint256 allowedAt, uint256 year, uint256 month, uint256 day)\n        private\n        pure\n        returns (uint256)\n    {\n        return\n            DateTime.timestampFromDateTime(\n                year,\n                month,\n                day,\n                allowedAt.getHour(),\n                allowedAt.getMinute(),\n                allowedAt.getSecond()\n            );\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/TokenIndexedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.3;\n\nimport '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\n\nimport '../interfaces/base/ITokenIndexedTask.sol';\n\n/**\n * @dev Token indexed task. It defines a token acceptance list to tell which are the tokens supported by the\n * task. Tokens acceptance can be configured either as an allow list or as a deny list.\n */\nabstract contract TokenIndexedTask is ITokenIndexedTask, Authorized {\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    // Acceptance list type\n    TokensAcceptanceType public override tokensAcceptanceType;\n\n    // Enumerable set of tokens included in the acceptance list\n    EnumerableSet.AddressSet internal _tokens;\n\n    /**\n     * @dev Token index config. Only used in the initializer.\n     * @param acceptanceType Token acceptance type to be set\n     * @param tokens List of token addresses to be set for the acceptance list\n     */\n    struct TokenIndexConfig {\n        TokensAcceptanceType acceptanceType;\n        address[] tokens;\n    }\n\n    /**\n     * @dev Initializes the token indexed task. It does not call upper contracts initializers.\n     * @param config Token indexed task config\n     */\n    function __TokenIndexedTask_init(TokenIndexConfig memory config) internal onlyInitializing {\n        __TokenIndexedTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the token indexed task. It does call upper contracts initializers.\n     * @param config Token indexed task config\n     */\n    function __TokenIndexedTask_init_unchained(TokenIndexConfig memory config) internal onlyInitializing {\n        _setTokensAcceptanceType(config.acceptanceType);\n\n        for (uint256 i = 0; i < config.tokens.length; i++) {\n            _setTokenAcceptanceList(config.tokens[i], true);\n        }\n    }\n\n    /**\n     * @dev Tells whether a token is allowed or not\n     * @param token Address of the token being queried\n     */\n    function isTokenAllowed(address token) public view override returns (bool) {\n        bool containsToken = _tokens.contains(token);\n        return tokensAcceptanceType == TokensAcceptanceType.AllowList ? containsToken : !containsToken;\n    }\n\n    /**\n     * @dev Sets the tokens acceptance type of the task\n     * @param newTokensAcceptanceType New token acceptance type to be set\n     */\n    function setTokensAcceptanceType(TokensAcceptanceType newTokensAcceptanceType)\n        external\n        override\n        authP(authParams(uint8(newTokensAcceptanceType)))\n    {\n        _setTokensAcceptanceType(newTokensAcceptanceType);\n    }\n\n    /**\n     * @dev Updates the list of tokens of the tokens acceptance list\n     * @param tokens List of tokens to be updated from the acceptance list\n     * @param added Whether each of the given tokens should be added or removed from the list\n     */\n    function setTokensAcceptanceList(address[] memory tokens, bool[] memory added) external override auth {\n        if (tokens.length != added.length) revert TaskAcceptanceInputLengthMismatch();\n        for (uint256 i = 0; i < tokens.length; i++) {\n            _setTokenAcceptanceList(tokens[i], added[i]);\n        }\n    }\n\n    /**\n     * @dev Before token indexed task hook\n     */\n    function _beforeTokenIndexedTask(address token, uint256) internal virtual {\n        if (!isTokenAllowed(token)) revert TaskTokenNotAllowed(token);\n    }\n\n    /**\n     * @dev After token indexed task hook\n     */\n    function _afterTokenIndexedTask(address token, uint256) internal virtual {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Sets the tokens acceptance type of the task\n     * @param newTokensAcceptanceType New token acceptance type to be set\n     */\n    function _setTokensAcceptanceType(TokensAcceptanceType newTokensAcceptanceType) internal {\n        tokensAcceptanceType = newTokensAcceptanceType;\n        emit TokensAcceptanceTypeSet(newTokensAcceptanceType);\n    }\n\n    /**\n     * @dev Updates a token from the tokens acceptance list\n     * @param token Token to be updated from the acceptance list\n     * @param added Whether the token should be added or removed from the list\n     */\n    function _setTokenAcceptanceList(address token, bool added) internal {\n        if (token == address(0)) revert TaskAcceptanceTokenZero();\n        added ? _tokens.add(token) : _tokens.remove(token);\n        emit TokensAcceptanceListSet(token, added);\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/TokenThresholdTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.3;\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\n\nimport '../interfaces/base/ITokenThresholdTask.sol';\n\n/**\n * @dev Token threshold task. It mainly works with token threshold configs that can be used to tell if\n * a specific token amount is compliant with certain minimum or maximum values. Token threshold tasks\n * make use of a default threshold config as a fallback in case there is no custom threshold defined for the token\n * being evaluated.\n */\nabstract contract TokenThresholdTask is ITokenThresholdTask, Authorized {\n    using FixedPoint for uint256;\n\n    // Default threshold\n    Threshold internal _defaultThreshold;\n\n    // Custom thresholds per token\n    mapping (address => Threshold) internal _customThresholds;\n\n    /**\n     * @dev Threshold defined by a token address and min/max values\n     */\n    struct Threshold {\n        address token;\n        uint256 min;\n        uint256 max;\n    }\n\n    /**\n     * @dev Custom token threshold config. Only used in the initializer.\n     */\n    struct CustomThresholdConfig {\n        address token;\n        Threshold threshold;\n    }\n\n    /**\n     * @dev Token threshold config. Only used in the initializer.\n     * @param defaultThreshold Default threshold to be set\n     * @param customThresholdConfigs List of custom threshold configs to be set\n     */\n    struct TokenThresholdConfig {\n        Threshold defaultThreshold;\n        CustomThresholdConfig[] customThresholdConfigs;\n    }\n\n    /**\n     * @dev Initializes the token threshold task. It does not call upper contracts initializers.\n     * @param config Token threshold task config\n     */\n    function __TokenThresholdTask_init(TokenThresholdConfig memory config) internal onlyInitializing {\n        __TokenThresholdTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the token threshold task. It does call upper contracts initializers.\n     * @param config Token threshold task config\n     */\n    function __TokenThresholdTask_init_unchained(TokenThresholdConfig memory config) internal onlyInitializing {\n        Threshold memory defaultThreshold = config.defaultThreshold;\n        _setDefaultTokenThreshold(defaultThreshold.token, defaultThreshold.min, defaultThreshold.max);\n\n        for (uint256 i = 0; i < config.customThresholdConfigs.length; i++) {\n            CustomThresholdConfig memory customThresholdConfig = config.customThresholdConfigs[i];\n            Threshold memory custom = customThresholdConfig.threshold;\n            _setCustomTokenThreshold(customThresholdConfig.token, custom.token, custom.min, custom.max);\n        }\n    }\n\n    /**\n     * @dev Tells the default token threshold\n     */\n    function defaultTokenThreshold() external view override returns (address thresholdToken, uint256 min, uint256 max) {\n        Threshold memory threshold = _defaultThreshold;\n        return (threshold.token, threshold.min, threshold.max);\n    }\n\n    /**\n     * @dev Tells the token threshold defined for a specific token\n     * @param token Address of the token being queried\n     */\n    function customTokenThreshold(address token)\n        external\n        view\n        override\n        returns (address thresholdToken, uint256 min, uint256 max)\n    {\n        Threshold memory threshold = _customThresholds[token];\n        return (threshold.token, threshold.min, threshold.max);\n    }\n\n    /**\n     * @dev Tells the threshold that should be used for a token, it prioritizes custom thresholds over the default one\n     * @param token Address of the token being queried\n     */\n    function getTokenThreshold(address token)\n        external\n        view\n        virtual\n        override\n        returns (address thresholdToken, uint256 min, uint256 max)\n    {\n        Threshold memory threshold = _getTokenThreshold(token);\n        return (threshold.token, threshold.min, threshold.max);\n    }\n\n    /**\n     * @dev Sets a new default threshold config\n     * @param thresholdToken New threshold token to be set\n     * @param min New threshold minimum to be set\n     * @param max New threshold maximum to be set\n     */\n    function setDefaultTokenThreshold(address thresholdToken, uint256 min, uint256 max)\n        external\n        override\n        authP(authParams(thresholdToken, min, max))\n    {\n        _setDefaultTokenThreshold(thresholdToken, min, max);\n    }\n\n    /**\n     * @dev Sets a custom token threshold\n     * @param token Address of the token to set a custom threshold for\n     * @param thresholdToken New custom threshold token to be set\n     * @param min New custom threshold minimum to be set\n     * @param max New custom threshold maximum to be set\n     */\n    function setCustomTokenThreshold(address token, address thresholdToken, uint256 min, uint256 max)\n        external\n        override\n        authP(authParams(token, thresholdToken, min, max))\n    {\n        _setCustomTokenThreshold(token, thresholdToken, min, max);\n    }\n\n    /**\n     * @dev Fetches a base/quote price\n     */\n    function _getPrice(address base, address quote) internal view virtual returns (uint256);\n\n    /**\n     * @dev Tells the threshold that should be used for a token, it prioritizes custom thresholds over the default one\n     * @param token Address of the token being queried\n     */\n    function _getTokenThreshold(address token) internal view returns (Threshold memory) {\n        Threshold storage customThreshold = _customThresholds[token];\n        return customThreshold.token == address(0) ? _defaultThreshold : customThreshold;\n    }\n\n    /**\n     * @dev Before token threshold task hook\n     */\n    function _beforeTokenThresholdTask(address token, uint256 amount) internal virtual {\n        Threshold memory threshold = _getTokenThreshold(token);\n        if (threshold.token == address(0)) return;\n\n        uint256 convertedAmount = threshold.token == token ? amount : amount.mulDown(_getPrice(token, threshold.token));\n        bool isValid = convertedAmount >= threshold.min && (threshold.max == 0 || convertedAmount <= threshold.max);\n        if (!isValid) revert TaskTokenThresholdNotMet(threshold.token, convertedAmount, threshold.min, threshold.max);\n    }\n\n    /**\n     * @dev After token threshold task hook\n     */\n    function _afterTokenThresholdTask(address, uint256) internal virtual {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Sets a new default threshold config\n     * @param thresholdToken New threshold token to be set\n     * @param min New threshold minimum to be set\n     * @param max New threshold maximum to be set\n     */\n    function _setDefaultTokenThreshold(address thresholdToken, uint256 min, uint256 max) internal {\n        _setTokenThreshold(_defaultThreshold, thresholdToken, min, max);\n        emit DefaultTokenThresholdSet(thresholdToken, min, max);\n    }\n\n    /**\n     * @dev Sets a custom of tokens thresholds\n     * @param token Address of the token to set a custom threshold for\n     * @param thresholdToken New custom threshold token to be set\n     * @param min New custom threshold minimum to be set\n     * @param max New custom threshold maximum to be set\n     */\n    function _setCustomTokenThreshold(address token, address thresholdToken, uint256 min, uint256 max) internal {\n        if (token == address(0)) revert TaskThresholdTokenZero();\n        _setTokenThreshold(_customThresholds[token], thresholdToken, min, max);\n        emit CustomTokenThresholdSet(token, thresholdToken, min, max);\n    }\n\n    /**\n     * @dev Sets a threshold\n     * @param threshold Threshold to be updated\n     * @param token New threshold token to be set\n     * @param min New threshold minimum to be set\n     * @param max New threshold maximum to be set\n     */\n    function _setTokenThreshold(Threshold storage threshold, address token, uint256 min, uint256 max) private {\n        // If there is no threshold, all values must be zero\n        bool isZeroThreshold = token == address(0) && min == 0 && max == 0;\n        bool isNonZeroThreshold = token != address(0) && (max == 0 || max >= min);\n        if (!isZeroThreshold && !isNonZeroThreshold) revert TaskInvalidThresholdInput(token, min, max);\n\n        threshold.token = token;\n        threshold.min = min;\n        threshold.max = max;\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/base/VolumeLimitedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-authorizer/contracts/Authorized.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\n\nimport '../interfaces/base/IVolumeLimitedTask.sol';\n\n/**\n * @dev Volume limit config for tasks. It allows setting volume limit per period of time.\n */\nabstract contract VolumeLimitedTask is IVolumeLimitedTask, Authorized {\n    using FixedPoint for uint256;\n\n    // Default volume limit\n    VolumeLimit internal _defaultVolumeLimit;\n\n    // Custom volume limits per token\n    mapping (address => VolumeLimit) internal _customVolumeLimits;\n\n    /**\n     * @dev Volume limit config\n     * @param token Address to measure the volume limit\n     */\n    struct VolumeLimit {\n        address token;\n        uint256 amount;\n        uint256 accrued;\n        uint256 period;\n        uint256 nextResetTime;\n    }\n\n    /**\n     * @dev Volume limit params. Only used in the initializer.\n     */\n    struct VolumeLimitParams {\n        address token;\n        uint256 amount;\n        uint256 period;\n    }\n\n    /**\n     * @dev Custom token volume limit config. Only used in the initializer.\n     */\n    struct CustomVolumeLimitConfig {\n        address token;\n        VolumeLimitParams volumeLimit;\n    }\n\n    /**\n     * @dev Volume limit config. Only used in the initializer.\n     */\n    struct VolumeLimitConfig {\n        VolumeLimitParams defaultVolumeLimit;\n        CustomVolumeLimitConfig[] customVolumeLimitConfigs;\n    }\n\n    /**\n     * @dev Initializes the volume limited task. It does call upper contracts initializers.\n     * @param config Volume limited task config\n     */\n    function __VolumeLimitedTask_init(VolumeLimitConfig memory config) internal onlyInitializing {\n        __VolumeLimitedTask_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the volume limited task. It does not call upper contracts initializers.\n     * @param config Volume limited task config\n     */\n    function __VolumeLimitedTask_init_unchained(VolumeLimitConfig memory config) internal onlyInitializing {\n        VolumeLimitParams memory defaultLimit = config.defaultVolumeLimit;\n        _setDefaultVolumeLimit(defaultLimit.token, defaultLimit.amount, defaultLimit.period);\n\n        for (uint256 i = 0; i < config.customVolumeLimitConfigs.length; i++) {\n            CustomVolumeLimitConfig memory customVolumeLimitConfig = config.customVolumeLimitConfigs[i];\n            VolumeLimitParams memory custom = customVolumeLimitConfig.volumeLimit;\n            _setCustomVolumeLimit(customVolumeLimitConfig.token, custom.token, custom.amount, custom.period);\n        }\n    }\n\n    /**\n     * @dev Tells the default volume limit set\n     */\n    function defaultVolumeLimit()\n        external\n        view\n        override\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime)\n    {\n        VolumeLimit memory limit = _defaultVolumeLimit;\n        return (limit.token, limit.amount, limit.accrued, limit.period, limit.nextResetTime);\n    }\n\n    /**\n     * @dev Tells the custom volume limit set for a specific token\n     * @param token Address of the token being queried\n     */\n    function customVolumeLimit(address token)\n        external\n        view\n        override\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime)\n    {\n        VolumeLimit memory limit = _customVolumeLimits[token];\n        return (limit.token, limit.amount, limit.accrued, limit.period, limit.nextResetTime);\n    }\n\n    /**\n     * @dev Tells the volume limit that should be used for a token, it prioritizes custom limits over the default one\n     * @param token Address of the token being queried\n     */\n    function getVolumeLimit(address token)\n        external\n        view\n        override\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime)\n    {\n        VolumeLimit memory limit = _getVolumeLimit(token);\n        return (limit.token, limit.amount, limit.accrued, limit.period, limit.nextResetTime);\n    }\n\n    /**\n     * @dev Sets a the default volume limit config\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function setDefaultVolumeLimit(address limitToken, uint256 limitAmount, uint256 limitPeriod)\n        external\n        override\n        authP(authParams(limitToken, limitAmount, limitPeriod))\n    {\n        _setDefaultVolumeLimit(limitToken, limitAmount, limitPeriod);\n    }\n\n    /**\n     * @dev Sets a custom volume limit\n     * @param token Address of the token to set a custom volume limit for\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function setCustomVolumeLimit(address token, address limitToken, uint256 limitAmount, uint256 limitPeriod)\n        external\n        override\n        authP(authParams(token, limitToken, limitAmount, limitPeriod))\n    {\n        _setCustomVolumeLimit(token, limitToken, limitAmount, limitPeriod);\n    }\n\n    /**\n     * @dev Fetches a base/quote price\n     */\n    function _getPrice(address base, address quote) internal view virtual returns (uint256);\n\n    /**\n     * @dev Tells the volume limit that should be used for a token, it prioritizes custom limits over the default one\n     * @param token Address of the token being queried\n     */\n    function _getVolumeLimit(address token) internal view returns (VolumeLimit storage) {\n        VolumeLimit storage customLimit = _customVolumeLimits[token];\n        return customLimit.token == address(0) ? _defaultVolumeLimit : customLimit;\n    }\n\n    /**\n     * @dev Before volume limited task hook\n     */\n    function _beforeVolumeLimitedTask(address token, uint256 amount) internal virtual {\n        VolumeLimit memory limit = _getVolumeLimit(token);\n        if (limit.token == address(0)) return;\n\n        uint256 amountInLimitToken = limit.token == token ? amount : amount.mulDown(_getPrice(token, limit.token));\n        uint256 processedVolume = amountInLimitToken + (block.timestamp < limit.nextResetTime ? limit.accrued : 0);\n        if (processedVolume > limit.amount) revert TaskVolumeLimitExceeded(limit.token, limit.amount, processedVolume);\n    }\n\n    /**\n     * @dev After volume limited task hook\n     */\n    function _afterVolumeLimitedTask(address token, uint256 amount) internal virtual {\n        VolumeLimit storage limit = _getVolumeLimit(token);\n        if (limit.token == address(0)) return;\n\n        uint256 amountInLimitToken = limit.token == token ? amount : amount.mulDown(_getPrice(token, limit.token));\n        if (block.timestamp >= limit.nextResetTime) {\n            limit.accrued = 0;\n            limit.nextResetTime = block.timestamp + limit.period;\n        }\n        limit.accrued += amountInLimitToken;\n    }\n\n    /**\n     * @dev Sets the default volume limit\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function _setDefaultVolumeLimit(address limitToken, uint256 limitAmount, uint256 limitPeriod) internal {\n        _setVolumeLimit(_defaultVolumeLimit, limitToken, limitAmount, limitPeriod);\n        emit DefaultVolumeLimitSet(limitToken, limitAmount, limitPeriod);\n    }\n\n    /**\n     * @dev Sets a custom volume limit\n     * @param token Address of the token to set a custom volume limit for\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function _setCustomVolumeLimit(address token, address limitToken, uint256 limitAmount, uint256 limitPeriod)\n        internal\n    {\n        if (token == address(0)) revert TaskVolumeLimitTokenZero();\n        _setVolumeLimit(_customVolumeLimits[token], limitToken, limitAmount, limitPeriod);\n        emit CustomVolumeLimitSet(token, limitToken, limitAmount, limitPeriod);\n    }\n\n    /**\n     * @dev Sets a volume limit\n     * @param limit Volume limit to be updated\n     * @param token Address of the token to measure the volume limit\n     * @param amount Amount of tokens to be applied for the volume limit\n     * @param period Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function _setVolumeLimit(VolumeLimit storage limit, address token, uint256 amount, uint256 period) private {\n        // If there is no limit, all values must be zero\n        bool isZeroLimit = token == address(0) && amount == 0 && period == 0;\n        bool isNonZeroLimit = token != address(0) && amount > 0 && period > 0;\n        if (!isZeroLimit && !isNonZeroLimit) revert TaskInvalidVolumeLimitInput(token, amount, period);\n\n        // Changing the period only affects the end time of the next period, but not the end date of the current one\n        limit.period = period;\n\n        // Changing the amount does not affect the totalizator, it only applies when updating the accrued amount.\n        // Note that it can happen that the new amount is lower than the accrued amount if the amount is lowered.\n        // However, there shouldn't be any accounting issues with that.\n        limit.amount = amount;\n\n        // Therefore, only clean the totalizators if the limit is being removed\n        if (isZeroLimit) {\n            limit.accrued = 0;\n            limit.nextResetTime = 0;\n        } else {\n            // If limit is not zero, set the next reset time if it wasn't set already\n            // Otherwise, if the token is being changed the accrued amount must be updated accordingly\n            if (limit.nextResetTime == 0) {\n                limit.accrued = 0;\n                limit.nextResetTime = block.timestamp + period;\n            } else if (limit.token != token) {\n                uint256 price = _getPrice(limit.token, token);\n                limit.accrued = limit.accrued.mulDown(price);\n            }\n        }\n\n        // Finally simply set the new requested token\n        limit.token = token;\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/IBaseTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorized.sol';\n\n/**\n * @dev Base task interface\n */\ninterface IBaseTask is IAuthorized {\n    // Execution type serves for relayers in order to distinguish how each task must be executed\n    // solhint-disable-next-line func-name-mixedcase\n    function EXECUTION_TYPE() external view returns (bytes32);\n\n    /**\n     * @dev The balance connectors are the same\n     */\n    error TaskSameBalanceConnectors(bytes32 connectorId);\n\n    /**\n     * @dev The smart vault's price oracle is not set\n     */\n    error TaskSmartVaultPriceOracleNotSet(address smartVault);\n\n    /**\n     * @dev Emitted every time a task is executed\n     */\n    event Executed();\n\n    /**\n     * @dev Emitted every time the balance connectors are set\n     */\n    event BalanceConnectorsSet(bytes32 indexed previous, bytes32 indexed next);\n\n    /**\n     * @dev Tells the address of the Smart Vault tied to it, it cannot be changed\n     */\n    function smartVault() external view returns (address);\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched.\n     * This address must be the Smart Vault in case the previous balance connector is set.\n     */\n    function getTokensSource() external view returns (address);\n\n    /**\n     * @dev Tells the amount a task should use for a token\n     * @param token Address of the token being queried\n     */\n    function getTaskAmount(address token) external view returns (uint256);\n\n    /**\n     * @dev Tells the previous and next balance connectors id of the previous task in the workflow\n     */\n    function getBalanceConnectors() external view returns (bytes32 previous, bytes32 next);\n\n    /**\n     * @dev Sets the balance connector IDs\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function setBalanceConnectors(bytes32 previous, bytes32 next) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/IGasLimitedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Gas limited task interface\n */\ninterface IGasLimitedTask is IBaseTask {\n    /**\n     * @dev The tx initial gas cache has not been initialized\n     */\n    error TaskGasNotInitialized();\n\n    /**\n     * @dev The gas price used is greater than the limit\n     */\n    error TaskGasPriceLimitExceeded(uint256 gasPrice, uint256 gasPriceLimit);\n\n    /**\n     * @dev The priority fee used is greater than the priority fee limit\n     */\n    error TaskPriorityFeeLimitExceeded(uint256 priorityFee, uint256 priorityFeeLimit);\n\n    /**\n     * @dev The transaction cost is greater than the transaction cost limit\n     */\n    error TaskTxCostLimitExceeded(uint256 txCost, uint256 txCostLimit);\n\n    /**\n     * @dev The transaction cost percentage is greater than the transaction cost limit percentage\n     */\n    error TaskTxCostLimitPctExceeded(uint256 txCostPct, uint256 txCostLimitPct);\n\n    /**\n     * @dev The new transaction cost limit percentage is greater than one\n     */\n    error TaskTxCostLimitPctAboveOne();\n\n    /**\n     * @dev Emitted every time the gas limits are set\n     */\n    event GasLimitsSet(uint256 gasPriceLimit, uint256 priorityFeeLimit, uint256 txCostLimit, uint256 txCostLimitPct);\n\n    /**\n     * @dev Tells the gas limits config\n     */\n    function getGasLimits()\n        external\n        view\n        returns (uint256 gasPriceLimit, uint256 priorityFeeLimit, uint256 txCostLimit, uint256 txCostLimitPct);\n\n    /**\n     * @dev Sets the gas limits config\n     * @param newGasPriceLimit New gas price limit to be set\n     * @param newPriorityFeeLimit New priority fee limit to be set\n     * @param newTxCostLimit New tx cost limit to be set\n     * @param newTxCostLimitPct New tx cost percentage limit to be set\n     */\n    function setGasLimits(\n        uint256 newGasPriceLimit,\n        uint256 newPriorityFeeLimit,\n        uint256 newTxCostLimit,\n        uint256 newTxCostLimitPct\n    ) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/IPausableTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Pausable task interface\n */\ninterface IPausableTask is IBaseTask {\n    /**\n     * @dev The task is paused\n     */\n    error TaskPaused();\n\n    /**\n     * @dev The task is unpaused\n     */\n    error TaskUnpaused();\n\n    /**\n     * @dev Emitted every time a task is paused\n     */\n    event Paused();\n\n    /**\n     * @dev Emitted every time a task is unpaused\n     */\n    event Unpaused();\n\n    /**\n     * @dev Tells the task is paused or not\n     */\n    function isPaused() external view returns (bool);\n\n    /**\n     * @dev Pauses a task\n     */\n    function pause() external;\n\n    /**\n     * @dev Unpauses a task\n     */\n    function unpause() external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/ITimeLockedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Time-locked task interface\n */\ninterface ITimeLockedTask is IBaseTask {\n    /**\n     * @dev The time lock frequency mode requested is invalid\n     */\n    error TaskInvalidFrequencyMode(uint8 mode);\n\n    /**\n     * @dev The time lock frequency is not valid\n     */\n    error TaskInvalidFrequency(uint8 mode, uint256 frequency);\n\n    /**\n     * @dev The time lock allowed date is not valid\n     */\n    error TaskInvalidAllowedDate(uint8 mode, uint256 date);\n\n    /**\n     * @dev The time lock allowed window is not valid\n     */\n    error TaskInvalidAllowedWindow(uint8 mode, uint256 window);\n\n    /**\n     * @dev The time lock is still active\n     */\n    error TaskTimeLockActive(uint256 currentTimestamp, uint256 expiration);\n\n    /**\n     * @dev Emitted every time a new time lock is set\n     */\n    event TimeLockSet(uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window);\n\n    /**\n     * @dev Emitted every time a new expiration timestamp is set\n     */\n    event TimeLockAllowedAtSet(uint256 allowedAt);\n\n    /**\n     * @dev Tells all the time-lock related information\n     */\n    function getTimeLock() external view returns (uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window);\n\n    /**\n     * @dev Sets the time-lock\n     * @param mode Time lock mode\n     * @param frequency Time lock frequency\n     * @param allowedAt Future timestamp since when the task can be executed\n     * @param window Period in seconds during when a time-locked task can be executed since the allowed timestamp\n     */\n    function setTimeLock(uint8 mode, uint256 frequency, uint256 allowedAt, uint256 window) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/ITokenIndexedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Token indexed task interface\n */\ninterface ITokenIndexedTask is IBaseTask {\n    /**\n     * @dev Acceptance list types: either deny-list to express \"all except\" or allow-list to express \"only\"\n     */\n    enum TokensAcceptanceType {\n        DenyList,\n        AllowList\n    }\n\n    /**\n     * @dev The acceptance token is zero\n     */\n    error TaskAcceptanceTokenZero();\n\n    /**\n     * @dev The tokens acceptance input length mismatch\n     */\n    error TaskAcceptanceInputLengthMismatch();\n\n    /**\n     * @dev The token is not allowed\n     */\n    error TaskTokenNotAllowed(address token);\n\n    /**\n     * @dev Emitted every time a tokens acceptance type is set\n     */\n    event TokensAcceptanceTypeSet(TokensAcceptanceType acceptanceType);\n\n    /**\n     * @dev Emitted every time a token is added or removed from the acceptance list\n     */\n    event TokensAcceptanceListSet(address indexed token, bool added);\n\n    /**\n     * @dev Tells the acceptance type of the config\n     */\n    function tokensAcceptanceType() external view returns (TokensAcceptanceType);\n\n    /**\n     * @dev Tells whether a token is allowed or not\n     * @param token Address of the token being queried\n     */\n    function isTokenAllowed(address token) external view returns (bool);\n\n    /**\n     * @dev Sets the tokens acceptance type of the task\n     * @param newTokensAcceptanceType New token acceptance type to be set\n     */\n    function setTokensAcceptanceType(TokensAcceptanceType newTokensAcceptanceType) external;\n\n    /**\n     * @dev Updates the list of tokens of the tokens acceptance list\n     * @param tokens List of tokens to be updated from the acceptance list\n     * @param added Whether each of the given tokens should be added or removed from the list\n     */\n    function setTokensAcceptanceList(address[] memory tokens, bool[] memory added) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/ITokenThresholdTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General External License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General External License for more details.\n\n// You should have received a copy of the GNU General External License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Token threshold task interface\n */\ninterface ITokenThresholdTask is IBaseTask {\n    /**\n     * @dev The token threshold token is zero\n     */\n    error TaskThresholdTokenZero();\n\n    /**\n     * @dev The token threshold to be set is invalid\n     */\n    error TaskInvalidThresholdInput(address token, uint256 min, uint256 max);\n\n    /**\n     * @dev The token threshold has not been met\n     */\n    error TaskTokenThresholdNotMet(address token, uint256 amount, uint256 min, uint256 max);\n\n    /**\n     * @dev Emitted every time a default threshold is set\n     */\n    event DefaultTokenThresholdSet(address token, uint256 min, uint256 max);\n\n    /**\n     * @dev Emitted every time a token threshold is set\n     */\n    event CustomTokenThresholdSet(address indexed token, address thresholdToken, uint256 min, uint256 max);\n\n    /**\n     * @dev Tells the default token threshold\n     */\n    function defaultTokenThreshold() external view returns (address thresholdToken, uint256 min, uint256 max);\n\n    /**\n     * @dev Tells the custom threshold defined for a specific token\n     * @param token Address of the token being queried\n     */\n    function customTokenThreshold(address token)\n        external\n        view\n        returns (address thresholdToken, uint256 min, uint256 max);\n\n    /**\n     * @dev Tells the threshold that should be used for a token\n     * @param token Address of the token being queried\n     */\n    function getTokenThreshold(address token) external view returns (address thresholdToken, uint256 min, uint256 max);\n\n    /**\n     * @dev Sets a new default threshold config\n     * @param thresholdToken New threshold token to be set\n     * @param min New threshold minimum to be set\n     * @param max New threshold maximum to be set\n     */\n    function setDefaultTokenThreshold(address thresholdToken, uint256 min, uint256 max) external;\n\n    /**\n     * @dev Sets a custom token threshold\n     * @param token Address of the token to set a custom threshold\n     * @param thresholdToken New custom threshold token to be set\n     * @param min New custom threshold minimum to be set\n     * @param max New custom threshold maximum to be set\n     */\n    function setCustomTokenThreshold(address token, address thresholdToken, uint256 min, uint256 max) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/base/IVolumeLimitedTask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './IBaseTask.sol';\n\n/**\n * @dev Volume limited task interface\n */\ninterface IVolumeLimitedTask is IBaseTask {\n    /**\n     * @dev The volume limit token is zero\n     */\n    error TaskVolumeLimitTokenZero();\n\n    /**\n     * @dev The volume limit to be set is invalid\n     */\n    error TaskInvalidVolumeLimitInput(address token, uint256 amount, uint256 period);\n\n    /**\n     * @dev The volume limit has been exceeded\n     */\n    error TaskVolumeLimitExceeded(address token, uint256 limit, uint256 volume);\n\n    /**\n     * @dev Emitted every time a default volume limit is set\n     */\n    event DefaultVolumeLimitSet(address indexed limitToken, uint256 amount, uint256 period);\n\n    /**\n     * @dev Emitted every time a custom volume limit is set\n     */\n    event CustomVolumeLimitSet(address indexed token, address indexed limitToken, uint256 amount, uint256 period);\n\n    /**\n     * @dev Tells the default volume limit set\n     */\n    function defaultVolumeLimit()\n        external\n        view\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime);\n\n    /**\n     * @dev Tells the custom volume limit set for a specific token\n     * @param token Address of the token being queried\n     */\n    function customVolumeLimit(address token)\n        external\n        view\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime);\n\n    /**\n     * @dev Tells the volume limit that should be used for a token\n     * @param token Address of the token being queried\n     */\n    function getVolumeLimit(address token)\n        external\n        view\n        returns (address limitToken, uint256 amount, uint256 accrued, uint256 period, uint256 nextResetTime);\n\n    /**\n     * @dev Sets a the default volume limit config\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function setDefaultVolumeLimit(address limitToken, uint256 limitAmount, uint256 limitPeriod) external;\n\n    /**\n     * @dev Sets a custom volume limit\n     * @param token Address of the token to set a custom volume limit for\n     * @param limitToken Address of the token to measure the volume limit\n     * @param limitAmount Amount of tokens to be applied for the volume limit\n     * @param limitPeriod Frequency to Amount of tokens to be applied for the volume limit\n     */\n    function setCustomVolumeLimit(address token, address limitToken, uint256 limitAmount, uint256 limitPeriod) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/ITask.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport './base/IBaseTask.sol';\nimport './base/IPausableTask.sol';\nimport './base/IGasLimitedTask.sol';\nimport './base/ITimeLockedTask.sol';\nimport './base/ITokenIndexedTask.sol';\nimport './base/ITokenThresholdTask.sol';\nimport './base/IVolumeLimitedTask.sol';\n\n// solhint-disable no-empty-blocks\n\n/**\n * @dev Task interface\n */\ninterface ITask is\n    IBaseTask,\n    IPausableTask,\n    IGasLimitedTask,\n    ITimeLockedTask,\n    ITokenIndexedTask,\n    ITokenThresholdTask,\n    IVolumeLimitedTask\n{\n\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/interfaces/primitives/IWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '../ITask.sol';\n\n/**\n * @dev Withdrawer task interface\n */\ninterface IWithdrawer is ITask {\n    /**\n     * @dev The token is zero\n     */\n    error TaskTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error TaskAmountZero();\n\n    /**\n     * @dev The recipient is zero\n     */\n    error TaskRecipientZero();\n\n    /**\n     * @dev The recipient to be set is the smart vault\n     */\n    error TaskRecipientEqualsSmartVault(address recipient);\n\n    /**\n     * @dev The next balance connector is not zero\n     */\n    error TaskNextConnectorNotZero(bytes32 id);\n\n    /**\n     * @dev Emitted every time the recipient is set\n     */\n    event RecipientSet(address indexed recipient);\n\n    /**\n     * @dev Tells the address of the allowed recipient\n     */\n    function recipient() external view returns (address);\n\n    /**\n     * @dev Sets the recipient address\n     * @param recipient Address of the new recipient to be set\n     */\n    function setRecipient(address recipient) external;\n\n    /**\n     * @dev Executes the withdrawer task\n     */\n    function call(address token, uint256 amount) external;\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/primitives/Withdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '../Task.sol';\nimport '../interfaces/primitives/IWithdrawer.sol';\n\n/**\n * @title Withdrawer\n * @dev Task that offers a recipient address where funds can be withdrawn\n */\ncontract Withdrawer is IWithdrawer, Task {\n    // Execution type for relayers\n    bytes32 public constant override EXECUTION_TYPE = keccak256('WITHDRAWER');\n\n    // Address where tokens will be transferred to\n    address public override recipient;\n\n    /**\n     * @dev Withdraw config. Only used in the initializer.\n     */\n    struct WithdrawConfig {\n        address recipient;\n        TaskConfig taskConfig;\n    }\n\n    /**\n     * @dev Initializes the withdrawer\n     * @param config Withdraw config\n     */\n    function initialize(WithdrawConfig memory config) external virtual initializer {\n        __Withdrawer_init(config);\n    }\n\n    /**\n     * @dev Initializes the withdrawer. It does call upper contracts initializers.\n     * @param config Withdraw config\n     */\n    function __Withdrawer_init(WithdrawConfig memory config) internal onlyInitializing {\n        __Task_init(config.taskConfig);\n        __Withdrawer_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the withdrawer. It does not call upper contracts initializers.\n     * @param config Withdraw config\n     */\n    function __Withdrawer_init_unchained(WithdrawConfig memory config) internal onlyInitializing {\n        _setRecipient(config.recipient);\n    }\n\n    /**\n     * @dev Sets the recipient address. Sender must be authorized.\n     * @param newRecipient Address of the new recipient to be set\n     */\n    function setRecipient(address newRecipient) external override authP(authParams(newRecipient)) {\n        _setRecipient(newRecipient);\n    }\n\n    /**\n     * @dev Executes the Withdrawer\n     */\n    function call(address token, uint256 amount) external virtual override authP(authParams(token, amount)) {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeWithdrawer(token, amount);\n        ISmartVault(smartVault).withdraw(token, recipient, amount);\n        _afterWithdrawer(token, amount);\n    }\n\n    /**\n     * @dev Before withdrawer hook\n     */\n    function _beforeWithdrawer(address token, uint256 amount) internal virtual {\n        _beforeTask(token, amount);\n        if (token == address(0)) revert TaskTokenZero();\n        if (amount == 0) revert TaskAmountZero();\n    }\n\n    /**\n     * @dev After withdrawer hook\n     */\n    function _afterWithdrawer(address token, uint256 amount) internal virtual {\n        _afterTask(token, amount);\n    }\n\n    /**\n     * @dev Sets the recipient address\n     * @param newRecipient Address of the new recipient to be set\n     */\n    function _setRecipient(address newRecipient) internal {\n        if (newRecipient == address(0)) revert TaskRecipientZero();\n        if (newRecipient == smartVault) revert TaskRecipientEqualsSmartVault(newRecipient);\n        recipient = newRecipient;\n        emit RecipientSet(newRecipient);\n    }\n\n    /**\n     * @dev Sets the balance connectors. Next balance connector must be unset.\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function _setBalanceConnectors(bytes32 previous, bytes32 next) internal virtual override {\n        if (next != bytes32(0)) revert TaskNextConnectorNotZero(next);\n        super._setBalanceConnectors(previous, next);\n    }\n}\n"
      },
      "@mimic-fi/v3-tasks/contracts/Task.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport './interfaces/ITask.sol';\nimport './base/BaseTask.sol';\nimport './base/PausableTask.sol';\nimport './base/GasLimitedTask.sol';\nimport './base/TimeLockedTask.sol';\nimport './base/TokenIndexedTask.sol';\nimport './base/TokenThresholdTask.sol';\nimport './base/VolumeLimitedTask.sol';\n\n/**\n * @title Task\n * @dev Shared components across all tasks\n */\nabstract contract Task is\n    ITask,\n    BaseTask,\n    PausableTask,\n    GasLimitedTask,\n    TimeLockedTask,\n    TokenIndexedTask,\n    TokenThresholdTask,\n    VolumeLimitedTask\n{\n    /**\n     * @dev Task config. Only used in the initializer.\n     */\n    struct TaskConfig {\n        BaseConfig baseConfig;\n        GasLimitConfig gasLimitConfig;\n        TimeLockConfig timeLockConfig;\n        TokenIndexConfig tokenIndexConfig;\n        TokenThresholdConfig tokenThresholdConfig;\n        VolumeLimitConfig volumeLimitConfig;\n    }\n\n    /**\n     * @dev Initializes the task. It does call upper contracts initializers.\n     * @param config Task config\n     */\n    function __Task_init(TaskConfig memory config) internal onlyInitializing {\n        __BaseTask_init(config.baseConfig);\n        __PausableTask_init();\n        __GasLimitedTask_init(config.gasLimitConfig);\n        __TimeLockedTask_init(config.timeLockConfig);\n        __TokenIndexedTask_init(config.tokenIndexConfig);\n        __TokenThresholdTask_init(config.tokenThresholdConfig);\n        __VolumeLimitedTask_init(config.volumeLimitConfig);\n        __Task_init_unchained(config);\n    }\n\n    /**\n     * @dev Initializes the task. It does not call upper contracts initializers.\n     * @param config Task config\n     */\n    function __Task_init_unchained(TaskConfig memory config) internal onlyInitializing {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Fetches a base/quote price\n     */\n    function _getPrice(address base, address quote)\n        internal\n        view\n        override(BaseTask, GasLimitedTask, TokenThresholdTask, VolumeLimitedTask)\n        returns (uint256)\n    {\n        return BaseTask._getPrice(base, quote);\n    }\n\n    /**\n     * @dev Before task hook\n     */\n    function _beforeTask(address token, uint256 amount) internal virtual {\n        _beforeBaseTask(token, amount);\n        _beforePausableTask(token, amount);\n        _beforeGasLimitedTask(token, amount);\n        _beforeTimeLockedTask(token, amount);\n        _beforeTokenIndexedTask(token, amount);\n        _beforeTokenThresholdTask(token, amount);\n        _beforeVolumeLimitedTask(token, amount);\n    }\n\n    /**\n     * @dev After task hook\n     */\n    function _afterTask(address token, uint256 amount) internal virtual {\n        _afterVolumeLimitedTask(token, amount);\n        _afterTokenThresholdTask(token, amount);\n        _afterTokenIndexedTask(token, amount);\n        _afterTimeLockedTask(token, amount);\n        _afterGasLimitedTask(token, amount);\n        _afterPausableTask(token, amount);\n        _afterBaseTask(token, amount);\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\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 of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\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._indexes[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 read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 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 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[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._indexes[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"
      },
      "@quant-finance/solidity-datetime/contracts/DateTime.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// ----------------------------------------------------------------------------\n// DateTime Library v2.0\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit      | Range         | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year      | 1970 ... 2345 |\n// month     | 1 ... 12      |\n// day       | 1 ... 31      |\n// hour      | 0 ... 23      |\n// minute    | 0 ... 59      |\n// second    | 0 ... 59      |\n// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\n// ----------------------------------------------------------------------------\n\nlibrary DateTime {\n    uint256 constant SECONDS_PER_DAY = 24 * 60 * 60;\n    uint256 constant SECONDS_PER_HOUR = 60 * 60;\n    uint256 constant SECONDS_PER_MINUTE = 60;\n    int256 constant OFFSET19700101 = 2440588;\n\n    uint256 constant DOW_MON = 1;\n    uint256 constant DOW_TUE = 2;\n    uint256 constant DOW_WED = 3;\n    uint256 constant DOW_THU = 4;\n    uint256 constant DOW_FRI = 5;\n    uint256 constant DOW_SAT = 6;\n    uint256 constant DOW_SUN = 7;\n\n    // ------------------------------------------------------------------------\n    // Calculate the number of days from 1970/01/01 to year/month/day using\n    // the date conversion algorithm from\n    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n    // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // days = day\n    //      - 32075\n    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4\n    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n    //      - offset\n    // ------------------------------------------------------------------------\n    function _daysFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 _days) {\n        require(year >= 1970);\n        int256 _year = int256(year);\n        int256 _month = int256(month);\n        int256 _day = int256(day);\n\n        int256 __days = _day - 32075 + (1461 * (_year + 4800 + (_month - 14) / 12)) / 4\n            + (367 * (_month - 2 - ((_month - 14) / 12) * 12)) / 12\n            - (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) / 4 - OFFSET19700101;\n\n        _days = uint256(__days);\n    }\n\n    // ------------------------------------------------------------------------\n    // Calculate year/month/day from the number of days since 1970/01/01 using\n    // the date conversion algorithm from\n    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n    // and adding the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // int L = days + 68569 + offset\n    // int N = 4 * L / 146097\n    // L = L - (146097 * N + 3) / 4\n    // year = 4000 * (L + 1) / 1461001\n    // L = L - 1461 * year / 4 + 31\n    // month = 80 * L / 2447\n    // dd = L - 2447 * month / 80\n    // L = month / 11\n    // month = month + 2 - 12 * L\n    // year = 100 * (N - 49) + year + L\n    // ------------------------------------------------------------------------\n    function _daysToDate(uint256 _days) internal pure returns (uint256 year, uint256 month, uint256 day) {\n        unchecked {\n            int256 __days = int256(_days);\n\n            int256 L = __days + 68569 + OFFSET19700101;\n            int256 N = (4 * L) / 146097;\n            L = L - (146097 * N + 3) / 4;\n            int256 _year = (4000 * (L + 1)) / 1461001;\n            L = L - (1461 * _year) / 4 + 31;\n            int256 _month = (80 * L) / 2447;\n            int256 _day = L - (2447 * _month) / 80;\n            L = _month / 11;\n            _month = _month + 2 - 12 * L;\n            _year = 100 * (N - 49) + _year + L;\n\n            year = uint256(_year);\n            month = uint256(_month);\n            day = uint256(_day);\n        }\n    }\n\n    function timestampFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 timestamp) {\n        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\n    }\n\n    function timestampFromDateTime(\n        uint256 year,\n        uint256 month,\n        uint256 day,\n        uint256 hour,\n        uint256 minute,\n        uint256 second\n    )\n        internal\n        pure\n        returns (uint256 timestamp)\n    {\n        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR\n            + minute * SECONDS_PER_MINUTE + second;\n    }\n\n    function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) {\n        unchecked {\n            (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        }\n    }\n\n    function timestampToDateTime(uint256 timestamp)\n        internal\n        pure\n        returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second)\n    {\n        unchecked {\n            (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n            uint256 secs = timestamp % SECONDS_PER_DAY;\n            hour = secs / SECONDS_PER_HOUR;\n            secs = secs % SECONDS_PER_HOUR;\n            minute = secs / SECONDS_PER_MINUTE;\n            second = secs % SECONDS_PER_MINUTE;\n        }\n    }\n\n    function isValidDate(uint256 year, uint256 month, uint256 day) internal pure returns (bool valid) {\n        if (year >= 1970 && month > 0 && month <= 12) {\n            uint256 daysInMonth = _getDaysInMonth(year, month);\n            if (day > 0 && day <= daysInMonth) {\n                valid = true;\n            }\n        }\n    }\n\n    function isValidDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second)\n        internal\n        pure\n        returns (bool valid)\n    {\n        if (isValidDate(year, month, day)) {\n            if (hour < 24 && minute < 60 && second < 60) {\n                valid = true;\n            }\n        }\n    }\n\n    function isLeapYear(uint256 timestamp) internal pure returns (bool leapYear) {\n        (uint256 year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        leapYear = _isLeapYear(year);\n    }\n\n    function _isLeapYear(uint256 year) internal pure returns (bool leapYear) {\n        leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\n    }\n\n    function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) {\n        weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\n    }\n\n    function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) {\n        weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\n    }\n\n    function getDaysInMonth(uint256 timestamp) internal pure returns (uint256 daysInMonth) {\n        (uint256 year, uint256 month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        daysInMonth = _getDaysInMonth(year, month);\n    }\n\n    function _getDaysInMonth(uint256 year, uint256 month) internal pure returns (uint256 daysInMonth) {\n        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {\n            daysInMonth = 31;\n        } else if (month != 2) {\n            daysInMonth = 30;\n        } else {\n            daysInMonth = _isLeapYear(year) ? 29 : 28;\n        }\n    }\n\n    // 1 = Monday, 7 = Sunday\n    function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) {\n        uint256 _days = timestamp / SECONDS_PER_DAY;\n        dayOfWeek = ((_days + 3) % 7) + 1;\n    }\n\n    function getYear(uint256 timestamp) internal pure returns (uint256 year) {\n        (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n\n    function getMonth(uint256 timestamp) internal pure returns (uint256 month) {\n        (, month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n\n    function getDay(uint256 timestamp) internal pure returns (uint256 day) {\n        (,, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n\n    function getHour(uint256 timestamp) internal pure returns (uint256 hour) {\n        uint256 secs = timestamp % SECONDS_PER_DAY;\n        hour = secs / SECONDS_PER_HOUR;\n    }\n\n    function getMinute(uint256 timestamp) internal pure returns (uint256 minute) {\n        uint256 secs = timestamp % SECONDS_PER_HOUR;\n        minute = secs / SECONDS_PER_MINUTE;\n    }\n\n    function getSecond(uint256 timestamp) internal pure returns (uint256 second) {\n        second = timestamp % SECONDS_PER_MINUTE;\n    }\n\n    function addYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {\n        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        year += _years;\n        uint256 daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);\n        require(newTimestamp >= timestamp);\n    }\n\n    function addMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {\n        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        month += _months;\n        year += (month - 1) / 12;\n        month = ((month - 1) % 12) + 1;\n        uint256 daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);\n        require(newTimestamp >= timestamp);\n    }\n\n    function addDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp + _days * SECONDS_PER_DAY;\n        require(newTimestamp >= timestamp);\n    }\n\n    function addHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\n        require(newTimestamp >= timestamp);\n    }\n\n    function addMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\n        require(newTimestamp >= timestamp);\n    }\n\n    function addSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp + _seconds;\n        require(newTimestamp >= timestamp);\n    }\n\n    function subYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {\n        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        year -= _years;\n        uint256 daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);\n        require(newTimestamp <= timestamp);\n    }\n\n    function subMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {\n        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        uint256 yearMonth = year * 12 + (month - 1) - _months;\n        year = yearMonth / 12;\n        month = (yearMonth % 12) + 1;\n        uint256 daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);\n        require(newTimestamp <= timestamp);\n    }\n\n    function subDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp - _days * SECONDS_PER_DAY;\n        require(newTimestamp <= timestamp);\n    }\n\n    function subHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\n        require(newTimestamp <= timestamp);\n    }\n\n    function subMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\n        require(newTimestamp <= timestamp);\n    }\n\n    function subSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {\n        newTimestamp = timestamp - _seconds;\n        require(newTimestamp <= timestamp);\n    }\n\n    function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _years) {\n        require(fromTimestamp <= toTimestamp);\n        (uint256 fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n        (uint256 toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n        _years = toYear - fromYear;\n    }\n\n    function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _months) {\n        require(fromTimestamp <= toTimestamp);\n        (uint256 fromYear, uint256 fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n        (uint256 toYear, uint256 toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n        _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\n    }\n\n    function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _days) {\n        require(fromTimestamp <= toTimestamp);\n        _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\n    }\n\n    function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _hours) {\n        require(fromTimestamp <= toTimestamp);\n        _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\n    }\n\n    function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _minutes) {\n        require(fromTimestamp <= toTimestamp);\n        _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\n    }\n\n    function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _seconds) {\n        require(fromTimestamp <= toTimestamp);\n        _seconds = toTimestamp - fromTimestamp;\n    }\n}\n"
      },
      "contracts/BalancerClaimer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/Task.sol';\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\n\nimport './interfaces/IBalancerClaimer.sol';\nimport './interfaces/IProtocolFeeWithdrawer.sol';\n\n/**\n * @title Balancer claimer\n * @dev Task used to claim tokens from Balancer's protocol fee withdrawer\n */\ncontract BalancerClaimer is IBalancerClaimer, Task {\n    // Execution type for relayers\n    bytes32 public constant override EXECUTION_TYPE = keccak256('BALANCER_CLAIMER');\n\n    // Protocol fee withdrawer address\n    address public override protocolFeeWithdrawer;\n\n    // Protocol fees collector address\n    address public override protocolFeesCollector;\n\n    /**\n     * @dev Initializes the balancer claimer\n     * @param config Task config\n     * @param withdrawer Protocol fee withdrawer address\n     */\n    function initializeBalancerClaimer(TaskConfig memory config, address withdrawer, address collector)\n        external\n        virtual\n        initializer\n    {\n        __BalancerClaimer_init(config, withdrawer, collector);\n    }\n\n    /**\n     * @dev Initializes the balancer claimer. It does call upper contracts initializers.\n     * @param config Task config\n     * @param withdrawer Protocol fee withdrawer address\n     */\n    function __BalancerClaimer_init(TaskConfig memory config, address withdrawer, address collector)\n        internal\n        onlyInitializing\n    {\n        __Task_init(config);\n        __BalancerClaimer_init_unchained(config, withdrawer, collector);\n    }\n\n    /**\n     * @dev Initializes the balancer claimer. It does not call upper contracts initializers.\n     * @param withdrawer Protocol fee withdrawer address\n     */\n    function __BalancerClaimer_init_unchained(TaskConfig memory, address withdrawer, address collector)\n        internal\n        onlyInitializing\n    {\n        _setProtocolFeeWithdrawer(withdrawer);\n        _setProtocolFeesCollector(collector);\n    }\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched\n     */\n    function getTokensSource() external view virtual override(IBaseTask, BaseTask) returns (address) {\n        return protocolFeesCollector;\n    }\n\n    /**\n     * @dev Tells the token balance in the protocol fees collector available for the smart vault\n     * @param token Address of the token being queried\n     */\n    function getTaskAmount(address token) public view virtual override(IBaseTask, BaseTask) returns (uint256) {\n        return ERC20Helpers.balanceOf(token, protocolFeesCollector);\n    }\n\n    /**\n     * @dev Sets the protocol fee withdrawer address. Sender must be authorized.\n     * @param newProtocolFeeWithdrawer Address of the protocol fee withdrawer to be set\n     */\n    function setProtocolFeeWithdrawer(address newProtocolFeeWithdrawer)\n        external\n        override\n        authP(authParams(newProtocolFeeWithdrawer))\n    {\n        _setProtocolFeeWithdrawer(newProtocolFeeWithdrawer);\n    }\n\n    /**\n     * @dev Sets the protocol fees collector address. Sender must be authorized.\n     * @param newProtocolFeesCollector Address of the protocol fees collector to be set\n     */\n    function setProtocolFeesCollector(address newProtocolFeesCollector)\n        external\n        override\n        authP(authParams(newProtocolFeesCollector))\n    {\n        _setProtocolFeesCollector(newProtocolFeesCollector);\n    }\n\n    /**\n     * @dev Executes the Balancer claimer task\n     */\n    function call(address token, uint256 amount) external override authP(authParams(token, amount)) {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeBalancerClaimer(token, amount);\n        // solhint-disable-next-line avoid-low-level-calls\n        ISmartVault(smartVault).call(protocolFeeWithdrawer, _buildBalancerClaimerData(token, amount), 0);\n        _afterBalancerClaimer(token, amount);\n    }\n\n    /**\n     * @dev Builds protocol fee withdrawer calldata\n     */\n    function _buildBalancerClaimerData(address token, uint256 amount) internal view returns (bytes memory) {\n        address[] memory tokens = new address[](1);\n        tokens[0] = token;\n        uint256[] memory amounts = new uint256[](1);\n        amounts[0] = amount;\n        return\n            abi.encodeWithSelector(IProtocolFeeWithdrawer.withdrawCollectedFees.selector, tokens, amounts, smartVault);\n    }\n\n    /**\n     * @dev Before balancer claimer task hook\n     */\n    function _beforeBalancerClaimer(address token, uint256 amount) internal {\n        _beforeTask(token, amount);\n        if (token == address(0)) revert TaskTokenZero();\n        if (amount == 0) revert TaskAmountZero();\n    }\n\n    /**\n     * @dev After balancer claimer task hook\n     */\n    function _afterBalancerClaimer(address token, uint256 amount) internal {\n        _increaseBalanceConnector(token, amount);\n        _afterTask(token, amount);\n    }\n\n    /**\n     * @dev Sets the protocol fee withdrawer address\n     * @param newProtocolFeeWithdrawer Address of the protocol fee withdrawer to be set\n     */\n    function _setProtocolFeeWithdrawer(address newProtocolFeeWithdrawer) internal {\n        if (newProtocolFeeWithdrawer == address(0)) revert TaskProtocolFeeWithdrawerZero();\n        protocolFeeWithdrawer = newProtocolFeeWithdrawer;\n        emit ProtocolFeeWithdrawerSet(newProtocolFeeWithdrawer);\n    }\n\n    /**\n     * @dev Sets the protocol fees collector address\n     * @param newProtocolFeesCollector Address of the protocol fees collector to be set\n     */\n    function _setProtocolFeesCollector(address newProtocolFeesCollector) internal {\n        if (newProtocolFeesCollector == address(0)) revert TaskProtocolFeesCollectorZero();\n        protocolFeesCollector = newProtocolFeesCollector;\n        emit ProtocolFeesCollectorSet(newProtocolFeesCollector);\n    }\n\n    /**\n     * @dev Sets the balance connectors. Previous balance connector must be unset.\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function _setBalanceConnectors(bytes32 previous, bytes32 next) internal virtual override {\n        if (previous != bytes32(0)) revert TaskPreviousConnectorNotZero(previous);\n        super._setBalanceConnectors(previous, next);\n    }\n}\n"
      },
      "contracts/CappedFeeWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-fee-controller/contracts/interfaces/IFeeController.sol';\nimport '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';\nimport '@mimic-fi/v3-tasks/contracts/primitives/Withdrawer.sol';\n\nimport './interfaces/ICappedFeeWithdrawer.sol';\nimport './interfaces/IWithdrawConnector.sol';\n\n/**\n * @title Capped Fee Withdrawer\n * @dev Task that offers a recipient address where funds can be withdrawn paying a fee up to a maximum cap\n */\ncontract CappedFeeWithdrawer is ICappedFeeWithdrawer, Withdrawer {\n    using FixedPoint for uint256;\n\n    /**\n     * @dev Fee cap information\n     * @param token Address of the token in which the cap is expressed\n     * @param cap Maximum amount of tokens that can be charged as a fee. Zero means no cap.\n     */\n    struct FeeCap {\n        address token;\n        uint256 cap;\n    }\n\n    // Connector address\n    address public override connector;\n\n    // Fee cap\n    FeeCap public override feeCap;\n\n    /**\n     * @dev Disables the default withdrawer initializer\n     */\n    function initialize(WithdrawConfig memory) external pure override {\n        revert TaskInitializerDisabled();\n    }\n\n    /**\n     * @dev Initializes the capped fee withdrawer\n     * @param config Withdraw config\n     * @param _connector Address of the connector to be set\n     * @param _feeCap Fee cap to be set\n     */\n    function initializeCappedFeeWithdrawer(WithdrawConfig memory config, address _connector, FeeCap memory _feeCap)\n        external\n        virtual\n        initializer\n    {\n        __CappedFeeWithdrawer_init(config, _connector, _feeCap);\n    }\n\n    /**\n     * @dev Initializes the capped fee withdrawer. It does call upper contracts initializers.\n     * @param config Withdraw config\n     * @param _connector Address of the connector to be set\n     * @param _feeCap Fee cap to be set\n     */\n    function __CappedFeeWithdrawer_init(WithdrawConfig memory config, address _connector, FeeCap memory _feeCap)\n        internal\n        onlyInitializing\n    {\n        __Withdrawer_init(config);\n        __CappedFeeWithdrawer_init_unchained(config, _connector, _feeCap);\n    }\n\n    /**\n     * @dev Initializes the capped fee withdrawer. It does not call upper contracts initializers.\n     * @param _connector Address of the connector to be set\n     * @param _feeCap Fee cap to be set\n     */\n    function __CappedFeeWithdrawer_init_unchained(WithdrawConfig memory, address _connector, FeeCap memory _feeCap)\n        internal\n        onlyInitializing\n    {\n        _setConnector(_connector);\n        _setFeeCap(_feeCap.token, _feeCap.cap);\n    }\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function setConnector(address newConnector) external override authP(authParams(newConnector)) {\n        _setConnector(newConnector);\n    }\n\n    /**\n     * @dev Sets a new fee cap\n     * @param token Address of the cap token to be set\n     * @param cap Max cap to be set\n     */\n    function setFeeCap(address token, uint256 cap) external override authP(authParams(token, cap)) {\n        _setFeeCap(token, cap);\n    }\n\n    /**\n     * @dev Executes the capped fee withdrawer\n     */\n    function call(address token, uint256 amount)\n        external\n        override(IWithdrawer, Withdrawer)\n        authP(authParams(token, amount))\n    {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeWithdrawer(token, amount);\n\n        (uint256 feeAmount, address collector) = _getFee(token, amount);\n        uint256 withdrawAmount = amount - feeAmount;\n        bytes memory connectorData = abi.encodeWithSelector(\n            IWithdrawConnector.execute.selector,\n            token,\n            recipient,\n            withdrawAmount,\n            collector,\n            feeAmount\n        );\n\n        ISmartVault(smartVault).execute(connector, connectorData);\n        _afterWithdrawer(token, amount);\n    }\n\n    /**\n     * @dev Tells the fee amount to be charged and the collector address\n     * @param token Address of the ERC20 token to collect the fee from\n     * @param amount Amount of tokens to collect the fee from\n     */\n    function _getFee(address token, uint256 amount) internal view returns (uint256, address) {\n        address _smartVault = smartVault;\n        address feeController = ISmartVault(_smartVault).feeController();\n        (, uint256 pct, address collector) = IFeeController(feeController).getFee(address(_smartVault));\n        uint256 feeAmountInToken = amount.mulDown(pct);\n        FeeCap memory _feeCap = feeCap;\n\n        if (_feeCap.cap > 0) {\n            uint256 price = _getPrice(_feeCap.token, token);\n            uint256 capInToken = _feeCap.cap.mulDown(price);\n            if (feeAmountInToken > capInToken) feeAmountInToken = capInToken;\n        }\n\n        return (feeAmountInToken, collector);\n    }\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function _setConnector(address newConnector) internal {\n        if (newConnector == address(0)) revert TaskConnectorZero();\n        connector = newConnector;\n        emit ConnectorSet(newConnector);\n    }\n\n    /**\n     * @dev Sets a new fee cap\n     * @param token Address of the cap token to be set\n     * @param cap Max cap to be set\n     */\n    function _setFeeCap(address token, uint256 cap) internal {\n        if (token == address(0) && cap != 0) revert TaskInvalidFeeCap();\n        feeCap.token = token;\n        feeCap.cap = cap;\n        emit FeeCapSet(token, cap);\n    }\n}\n"
      },
      "contracts/interfaces/IBalancerClaimer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/interfaces/ITask.sol';\n\nimport './IProtocolFeeWithdrawer.sol';\n\n/**\n * @title Balancer claimer interface\n */\ninterface IBalancerClaimer is ITask {\n    /**\n     * @dev The token is zero\n     */\n    error TaskTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error TaskAmountZero();\n\n    /**\n     * @dev The protocol fee withdrawer is zero\n     */\n    error TaskProtocolFeeWithdrawerZero();\n\n    /**\n     * @dev The protocol fees collector is zero\n     */\n    error TaskProtocolFeesCollectorZero();\n\n    /**\n     * @dev The previous balance connector is not zero\n     */\n    error TaskPreviousConnectorNotZero(bytes32 id);\n\n    /**\n     * @dev Emitted every time the protocol fee withdrawer is set\n     */\n    event ProtocolFeeWithdrawerSet(address indexed protocolFeeWithdrawer);\n\n    /**\n     * @dev Emitted every time the protocol fees collector is set\n     */\n    event ProtocolFeesCollectorSet(address indexed protocolFeesCollector);\n\n    /**\n     * @dev Tells the protocol fee withdrawer address\n     */\n    function protocolFeeWithdrawer() external view returns (address);\n\n    /**\n     * @dev Tells the protocol fee collector address\n     */\n    function protocolFeesCollector() external view returns (address);\n\n    /**\n     * @dev Sets the protocol fee withdrawer address. Sender must be authorized.\n     * @param newProtocolFeeWithdrawer Address of the protocol fee withdrawer to be set\n     */\n    function setProtocolFeeWithdrawer(address newProtocolFeeWithdrawer) external;\n\n    /**\n     * @dev Sets the protocol fees collector address. Sender must be authorized.\n     * @param newProtocolFeesCollector Address of the protocol fees collector to be set\n     */\n    function setProtocolFeesCollector(address newProtocolFeesCollector) external;\n\n    /**\n     * @dev Executes the Balancer claimer task\n     */\n    function call(address token, uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/ICappedFeeWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/interfaces/primitives/IWithdrawer.sol';\n\n/**\n * @title Capped Fee Withdrawer interface\n */\ninterface ICappedFeeWithdrawer is IWithdrawer {\n    /**\n     * @dev The task initializer is disabled\n     */\n    error TaskInitializerDisabled();\n\n    /**\n     * @dev The connector is zero\n     */\n    error TaskConnectorZero();\n\n    /**\n     * @dev The fee cap is invalid\n     */\n    error TaskInvalidFeeCap();\n\n    /**\n     * @dev Emitted every time the connector is set\n     */\n    event ConnectorSet(address indexed connector);\n\n    /**\n     * @dev Emitted every time the fee cap is set\n     */\n    event FeeCapSet(address indexed token, uint256 cap);\n\n    /**\n     * @dev Tells the connector tied to the task\n     */\n    function connector() external view returns (address);\n\n    /**\n     * @dev Tells the fee cap\n     */\n    function feeCap() external view returns (address token, uint256 cap);\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function setConnector(address newConnector) external;\n\n    /**\n     * @dev Sets a new fee cap\n     * @param token Address of the cap token to be set\n     * @param cap Max cap to be set\n     */\n    function setFeeCap(address token, uint256 cap) external;\n}\n"
      },
      "contracts/interfaces/IMigrationClaimer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/interfaces/ITask.sol';\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\n\n/**\n * @title Balancer claimer interface\n */\ninterface IMigrationClaimer is ITask {\n    /**\n     * @dev The token is zero\n     */\n    error TaskTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error TaskAmountZero();\n\n    /**\n     * @dev The source smart vault is zero\n     */\n    error TaskSourceSmartVaultZero();\n\n    /**\n     * @dev The previous balance connector is not zero\n     */\n    error TaskPreviousConnectorNotZero(bytes32 id);\n\n    /**\n     * @dev Emitted every time the source smart vault is set\n     */\n    event SourceSmartVaultSet(address indexed sourceSmartVault);\n\n    /**\n     * @dev Tells the source smart vault address\n     */\n    function sourceSmartVault() external view returns (address);\n\n    /**\n     * @dev Sets the source smart vault address. Sender must be authorized.\n     * @param newSourceSmartVault Address of the source smart vault to be set\n     */\n    function setSourceSmartVault(address newSourceSmartVault) external;\n\n    /**\n     * @dev Executes the Migration claimer task\n     */\n    function call(address token, uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/IOldSmartVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\ninterface IOldSmartVault {\n    /**\n     * @dev Withdraw tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param amount Amount of tokens to withdraw\n     * @param recipient Address where the tokens will be transferred to\n     * @param data Extra data that may enable or not different behaviors depending on the implementation\n     * @return withdrawn Amount of tokens transferred to the recipient address\n     */\n    function withdraw(address token, uint256 amount, address recipient, bytes memory data)\n        external\n        returns (uint256 withdrawn);\n}\n"
      },
      "contracts/interfaces/IProtocolFeeWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\ninterface IProtocolFeeWithdrawer {\n    function withdrawCollectedFees(address[] calldata tokens, uint256[] calldata amounts, address recipient) external;\n}\n"
      },
      "contracts/interfaces/ISmartVaultV2.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\ninterface ISmartVaultV2 {\n    function withdraw(address token, uint256 amount, address recipient, bytes memory data)\n        external\n        returns (uint256 withdrawn);\n}\n"
      },
      "contracts/interfaces/IV2SmartVaultMigrator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/interfaces/ITask.sol';\n\n/**\n * @title V2 Smart Vault Migrator interface\n */\ninterface IV2SmartVaultMigrator is ITask {\n    /**\n     * @dev The token is zero\n     */\n    error TaskTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error TaskAmountZero();\n\n    /**\n     * @dev The source smart vault is zero\n     */\n    error TaskSourceSmartVaultZero();\n\n    /**\n     * @dev The previous balance connector is not zero\n     */\n    error TaskPreviousConnectorNotZero(bytes32 id);\n\n    /**\n     * @dev Emitted every time the source smart vault is set\n     */\n    event SourceSmartVaultSet(address indexed sourceSmartVault);\n\n    /**\n     * @dev Tells the source smart vault address\n     */\n    function sourceSmartVault() external view returns (address);\n\n    /**\n     * @dev Sets the source smart vault address. Sender must be authorized.\n     * @param newSourceSmartVault Address of the source smart vault to be set\n     */\n    function setSourceSmartVault(address newSourceSmartVault) external;\n\n    /**\n     * @dev Executes the v2 smart vault migrator task\n     */\n    function call(address token, uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/IWithdrawConnector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\n/**\n * @title WithdrawConnector interface\n */\ninterface IWithdrawConnector {\n    /**\n     * @dev Emitted every time a withdrawal is executed\n     */\n    event Withdrawn(address indexed token, address indexed recipient, uint256 amount, uint256 fee);\n\n    /**\n     * @dev Withdraws ERC20 or native tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param recipient Address where the tokens will be transferred to\n     * @param amount Amount of tokens to withdraw\n     * @param collector Address where the fee will be transferred to\n     * @param feeAmount Amount of tokens to be charged as a fee\n     */\n    function execute(address token, address recipient, uint256 amount, address collector, uint256 feeAmount) external;\n}\n"
      },
      "contracts/interfaces/IZeroFeeWithdrawConnector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\n/**\n * @title ZeroFeeWithdrawConnector interface\n */\ninterface IZeroFeeWithdrawConnector {\n    /**\n     * @dev Emitted every time a withdrawal is executed\n     */\n    event Withdrawn(address indexed token, address indexed recipient, uint256 amount, uint256 fee);\n\n    /**\n     * @dev Withdraws ERC20 or native tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param recipient Address where the tokens will be transferred to\n     * @param amount Amount of tokens to withdraw\n     */\n    function execute(address token, address recipient, uint256 amount) external;\n}\n"
      },
      "contracts/interfaces/IZeroFeeWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/interfaces/primitives/IWithdrawer.sol';\n\n/**\n * @title Zero-fee Withdrawer interface\n */\ninterface IZeroFeeWithdrawer is IWithdrawer {\n    /**\n     * @dev The task initializer is disabled\n     */\n    error TaskInitializerDisabled();\n\n    /**\n     * @dev The connector is zero\n     */\n    error TaskConnectorZero();\n\n    /**\n     * @dev Emitted every time the connector is set\n     */\n    event ConnectorSet(address indexed connector);\n\n    /**\n     * @dev Tells the connector tied to the task\n     */\n    function connector() external view returns (address);\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function setConnector(address newConnector) external;\n}\n"
      },
      "contracts/MigrationClaimer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/Task.sol';\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\n\nimport './interfaces/IMigrationClaimer.sol';\nimport './interfaces/IOldSmartVault.sol';\n\n/**\n * @title Balancer claimer\n * @dev Task used to claim tokens from Balancer's Source smart vault\n */\ncontract MigrationClaimer is IMigrationClaimer, Task {\n    // Execution type for relayers\n    bytes32 public constant override EXECUTION_TYPE = keccak256('MIGRATION_CLAIMER');\n\n    // Source smart vault address\n    address public override sourceSmartVault;\n\n    /**\n     * @dev Initializes the balancer claimer\n     * @param config Task config\n     * @param smartVault Source smart vault address\n     */\n    function initializeMigrationClaimer(TaskConfig memory config, address smartVault) external virtual initializer {\n        __MigrationClaimer_init(config, smartVault);\n    }\n\n    /**\n     * @dev Initializes the balancer claimer. It does call upper contracts initializers.\n     * @param config Task config\n     * @param smartVault Source smart vault address\n     */\n    function __MigrationClaimer_init(TaskConfig memory config, address smartVault) internal onlyInitializing {\n        __Task_init(config);\n        __MigrationClaimer_init_unchained(config, smartVault);\n    }\n\n    /**\n     * @dev Initializes the balancer claimer. It does not call upper contracts initializers.\n     * @param smartVault Source smart vault address\n     */\n    function __MigrationClaimer_init_unchained(TaskConfig memory, address smartVault) internal onlyInitializing {\n        _setSourceSmartVault(smartVault);\n    }\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched\n     */\n    function getTokensSource() external view virtual override(IBaseTask, BaseTask) returns (address) {\n        return sourceSmartVault;\n    }\n\n    /**\n     * @dev Tells the token balance in the source smart vault\n     * @param token Address of the token being queried\n     */\n    function getTaskAmount(address token) public view virtual override(IBaseTask, BaseTask) returns (uint256) {\n        return ERC20Helpers.balanceOf(token, sourceSmartVault);\n    }\n\n    /**\n     * @dev Sets the Source smart vault address. Sender must be authorized.\n     * @param newSourceSmartVault Address of the Source smart vault to be set\n     */\n    function setSourceSmartVault(address newSourceSmartVault) external override authP(authParams(newSourceSmartVault)) {\n        _setSourceSmartVault(newSourceSmartVault);\n    }\n\n    /**\n     * @dev Executes the Balancer claimer task\n     */\n    function call(address token, uint256 amount) external override authP(authParams(token, amount)) {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeMigrationClaimer(token, amount);\n        // solhint-disable-next-line avoid-low-level-calls\n        ISmartVault(smartVault).call(sourceSmartVault, _buildMigrationClaimerData(token, amount), 0);\n        _afterMigrationClaimer(token, amount);\n    }\n\n    /**\n     * @dev Builds Source smart vault calldata\n     */\n    function _buildMigrationClaimerData(address token, uint256 amount) internal view returns (bytes memory) {\n        return abi.encodeWithSelector(IOldSmartVault.withdraw.selector, token, amount, smartVault, '0x');\n    }\n\n    /**\n     * @dev Before balancer claimer task hook\n     */\n    function _beforeMigrationClaimer(address token, uint256 amount) internal {\n        _beforeTask(token, amount);\n        if (token == address(0)) revert TaskTokenZero();\n        if (amount == 0) revert TaskAmountZero();\n    }\n\n    /**\n     * @dev After balancer claimer task hook\n     */\n    function _afterMigrationClaimer(address token, uint256 amount) internal {\n        _increaseBalanceConnector(token, amount);\n        _afterTask(token, amount);\n    }\n\n    /**\n     * @dev Sets the Source smart vault address\n     * @param newSourceSmartVault Address of the Source smart vault to be set\n     */\n    function _setSourceSmartVault(address newSourceSmartVault) internal {\n        if (newSourceSmartVault == address(0)) revert TaskSourceSmartVaultZero();\n        sourceSmartVault = newSourceSmartVault;\n        emit SourceSmartVaultSet(newSourceSmartVault);\n    }\n\n    /**\n     * @dev Sets the balance connectors. Previous balance connector must be unset.\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function _setBalanceConnectors(bytes32 previous, bytes32 next) internal virtual override {\n        if (previous != bytes32(0)) revert TaskPreviousConnectorNotZero(previous);\n        super._setBalanceConnectors(previous, next);\n    }\n}\n"
      },
      "contracts/test/ProtocolFeeWithdrawerMock.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '../interfaces/IProtocolFeeWithdrawer.sol';\n\ncontract ProtocolFeeWithdrawerMock is IProtocolFeeWithdrawer {\n    using SafeERC20 for IERC20;\n\n    // Protocol fees collector address\n    address public protocolFeesCollector;\n\n    constructor(address _protocolFeesCollector) {\n        protocolFeesCollector = _protocolFeesCollector;\n    }\n\n    function withdrawCollectedFees(address[] calldata tokens, uint256[] calldata amounts, address recipient)\n        external\n        override\n    {\n        require(tokens.length == amounts.length, 'WITHDRAWER_INVALID_INPUT_LEN');\n        for (uint256 i = 0; i < tokens.length; i++) {\n            require(IERC20(tokens[i]).balanceOf(protocolFeesCollector) >= amounts[i], 'INVALID_WITHDRAWER_BALANCE');\n            IERC20(tokens[i]).safeTransferFrom(protocolFeesCollector, recipient, amounts[i]);\n        }\n    }\n}\n"
      },
      "contracts/test/SmartVaultV2Mock.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\n\nimport '../interfaces/ISmartVaultV2.sol';\n\ncontract SmartVaultV2Mock is ISmartVaultV2 {\n    receive() external payable {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    function withdraw(address token, uint256 amount, address recipient, bytes memory)\n        external\n        returns (uint256 withdrawn)\n    {\n        ERC20Helpers.transfer(token, recipient, amount);\n        return amount;\n    }\n}\n"
      },
      "contracts/test/WithdrawConnectorMock.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '../WithdrawConnector.sol';\n\ncontract WithdrawConnectorMock is WithdrawConnector {\n    receive() external payable {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n}\n"
      },
      "contracts/test/ZeroFeeWithdrawConnectorMock.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '../ZeroFeeWithdrawConnector.sol';\n\ncontract ZeroFeeWithdrawConnectorMock is ZeroFeeWithdrawConnector {\n    receive() external payable {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n}\n"
      },
      "contracts/V2SmartVaultMigrator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\nimport '@mimic-fi/v3-tasks/contracts/Task.sol';\n\nimport './interfaces/IV2SmartVaultMigrator.sol';\nimport './interfaces/ISmartVaultV2.sol';\n\n/**\n * @title V2 Smart Vault Migrator\n * @dev Task used to withdraw tokens from BT's V2 smart vault\n */\ncontract V2SmartVaultMigrator is IV2SmartVaultMigrator, Task {\n    // Execution type for relayers\n    bytes32 public constant override EXECUTION_TYPE = keccak256('V2_SMART_VAULT_MIGRATOR');\n\n    // Reference to the source smart vault\n    address public override sourceSmartVault;\n\n    /**\n     * @dev Initializes the v2 smart vault migrator\n     * @param config Task config\n     * @param source Address of the source smart vault\n     */\n    function initializeV2SmartVaultMigrator(TaskConfig memory config, address source) external initializer {\n        __V2SmartVaultMigrator_init(config, source);\n    }\n\n    /**\n     * @dev Initializes the v2 smart vault migrator. It does call upper contracts initializers.\n     * @param config Task config\n     * @param source Address of the source smart vault\n     */\n    function __V2SmartVaultMigrator_init(TaskConfig memory config, address source) internal onlyInitializing {\n        __Task_init(config);\n        __V2SmartVaultMigrator_init_unchained(config, source);\n    }\n\n    /**\n     * @dev Initializes the v2 smart vault migrator. It does not call upper contracts initializers.\n     * @param source Address of the source smart vault\n     */\n    function __V2SmartVaultMigrator_init_unchained(TaskConfig memory, address source) internal onlyInitializing {\n        _setSourceSmartVault(source);\n    }\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched\n     */\n    function getTokensSource() public view override(IBaseTask, BaseTask) returns (address) {\n        return sourceSmartVault;\n    }\n\n    /**\n     * @dev Tells the token balance in the source smart vault\n     * @param token Address of the token being queried\n     */\n    function getTaskAmount(address token) public view override(IBaseTask, BaseTask) returns (uint256) {\n        return ERC20Helpers.balanceOf(token, getTokensSource());\n    }\n\n    /**\n     * @dev Sets the source smart vault address. Sender must be authorized.\n     * @param newSourceSmartVault Address of the source smart vault to be set\n     */\n    function setSourceSmartVault(address newSourceSmartVault) external override authP(authParams(newSourceSmartVault)) {\n        _setSourceSmartVault(newSourceSmartVault);\n    }\n\n    /**\n     * @dev Executes the v2 smart vault migrator task\n     */\n    function call(address token, uint256 amount) external override authP(authParams(token, amount)) {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeV2SmartVaultMigrator(token, amount);\n        bytes memory data = abi.encodeWithSelector(\n            ISmartVaultV2.withdraw.selector,\n            token,\n            amount,\n            smartVault,\n            new bytes(0)\n        );\n        // solhint-disable-next-line avoid-low-level-calls\n        ISmartVault(smartVault).call(sourceSmartVault, data, 0);\n        _afterV2SmartVaultMigrator(token, amount);\n    }\n\n    /**\n     * @dev Before v2 smart vault migrator task hook\n     */\n    function _beforeV2SmartVaultMigrator(address token, uint256 amount) internal {\n        _beforeTask(token, amount);\n        if (token == address(0)) revert TaskTokenZero();\n        if (amount == 0) revert TaskAmountZero();\n    }\n\n    /**\n     * @dev After v2 smart vault migrator task hook\n     */\n    function _afterV2SmartVaultMigrator(address token, uint256 amount) internal {\n        _increaseBalanceConnector(token, amount);\n        _afterTask(token, amount);\n    }\n\n    /**\n     * @dev Sets the source smart vault address\n     * @param newSourceSmartVault Address of the source smart vault to be set\n     */\n    function _setSourceSmartVault(address newSourceSmartVault) internal {\n        if (newSourceSmartVault == address(0)) revert TaskSourceSmartVaultZero();\n        sourceSmartVault = newSourceSmartVault;\n        emit SourceSmartVaultSet(newSourceSmartVault);\n    }\n\n    /**\n     * @dev Sets the balance connectors. Previous balance connector must be unset.\n     * @param previous Balance connector id of the previous task in the workflow\n     * @param next Balance connector id of the next task in the workflow\n     */\n    function _setBalanceConnectors(bytes32 previous, bytes32 next) internal override {\n        if (previous != bytes32(0)) revert TaskPreviousConnectorNotZero(previous);\n        super._setBalanceConnectors(previous, next);\n    }\n}\n"
      },
      "contracts/WithdrawConnector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\n\nimport './interfaces/IWithdrawConnector.sol';\n\n/**\n * @title Withdraw connector\n * @dev Uses ERC20 helpers lib to withdraw ERC20 or native tokens\n */\ncontract WithdrawConnector is IWithdrawConnector {\n    /**\n     * @dev Creates a new WithdrawConnector contract\n     */\n    constructor() {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Withdraws ERC20 or native tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param recipient Address where the tokens will be transferred to\n     * @param amount Amount of tokens to withdraw\n     * @param feeAmount Amount of tokens to be charged as a fee\n     * @param collector Address where the fee will be transferred to\n     */\n    function execute(address token, address recipient, uint256 amount, address collector, uint256 feeAmount) external {\n        if (amount > 0) ERC20Helpers.transfer(token, recipient, amount);\n        if (feeAmount > 0) ERC20Helpers.transfer(token, collector, feeAmount);\n        emit Withdrawn(token, recipient, amount, feeAmount);\n    }\n}\n"
      },
      "contracts/ZeroFeeWithdrawConnector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.17;\n\nimport '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';\n\nimport './interfaces/IZeroFeeWithdrawConnector.sol';\n\n/**\n * @title Zero-fee Withdraw connector\n * @dev Uses ERC20 helpers lib to withdraw ERC20 or native tokens\n */\ncontract ZeroFeeWithdrawConnector is IZeroFeeWithdrawConnector {\n    /**\n     * @dev Creates a new ZeroFeeWithdrawConnector contract\n     */\n    constructor() {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    /**\n     * @dev Withdraws ERC20 or native tokens to an external account\n     * @param token Address of the token to be withdrawn\n     * @param recipient Address where the tokens will be transferred to\n     * @param amount Amount of tokens to withdraw\n     */\n    function execute(address token, address recipient, uint256 amount) external {\n        if (amount > 0) ERC20Helpers.transfer(token, recipient, amount);\n        emit Withdrawn(token, recipient, amount, 0);\n    }\n}\n"
      },
      "contracts/ZeroFeeWithdrawer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\nimport '@mimic-fi/v3-tasks/contracts/primitives/Withdrawer.sol';\n\nimport './interfaces/IZeroFeeWithdrawConnector.sol';\nimport './interfaces/IZeroFeeWithdrawer.sol';\n\n/**\n * @title Zero-fee Withdrawer\n * @dev Task that offers a recipient address where funds can be withdrawn without paying fees\n */\ncontract ZeroFeeWithdrawer is IZeroFeeWithdrawer, Withdrawer {\n    // Connector address\n    address public override connector;\n\n    /**\n     * @dev Disables the default withdrawer initializer\n     */\n    function initialize(WithdrawConfig memory) external pure override {\n        revert TaskInitializerDisabled();\n    }\n\n    /**\n     * @dev Initializes the zero-fee withdrawer\n     * @param config Withdraw config\n     * @param _connector Address of the connector to be set\n     */\n    function initializeZeroFeeWithdrawer(WithdrawConfig memory config, address _connector)\n        external\n        virtual\n        initializer\n    {\n        __ZeroFeeWithdrawer_init(config, _connector);\n    }\n\n    /**\n     * @dev Initializes the zero-fee withdrawer. It does call upper contracts initializers.\n     * @param config Withdraw config\n     * @param _connector Address of the connector to be set\n     */\n    function __ZeroFeeWithdrawer_init(WithdrawConfig memory config, address _connector) internal onlyInitializing {\n        __Withdrawer_init(config);\n        __ZeroFeeWithdrawer_init_unchained(config, _connector);\n    }\n\n    /**\n     * @dev Initializes the zero-fee withdrawer. It does not call upper contracts initializers.\n     * @param _connector Address of the connector to be set\n     */\n    function __ZeroFeeWithdrawer_init_unchained(WithdrawConfig memory, address _connector) internal onlyInitializing {\n        _setConnector(_connector);\n    }\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function setConnector(address newConnector) external override authP(authParams(newConnector)) {\n        _setConnector(newConnector);\n    }\n\n    /**\n     * @dev Executes the zero-fee withdrawer\n     */\n    function call(address token, uint256 amount)\n        external\n        override(IWithdrawer, Withdrawer)\n        authP(authParams(token, amount))\n    {\n        if (amount == 0) amount = getTaskAmount(token);\n        _beforeWithdrawer(token, amount);\n\n        bytes memory connectorData = abi.encodeWithSelector(\n            IZeroFeeWithdrawConnector.execute.selector,\n            token,\n            recipient,\n            amount\n        );\n\n        ISmartVault(smartVault).execute(connector, connectorData);\n        _afterWithdrawer(token, amount);\n    }\n\n    /**\n     * @dev Sets a new connector\n     * @param newConnector Address of the connector to be set\n     */\n    function _setConnector(address newConnector) internal {\n        if (newConnector == address(0)) revert TaskConnectorZero();\n        connector = newConnector;\n        emit ConnectorSet(newConnector);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}