creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@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-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/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 balance connector id of the previous task in the workflow\n     */\n    function previousBalanceConnectorId() external view returns (bytes32);\n\n    /**\n     * @dev Tells the balance connector id of the next task in the workflow\n     */\n    function nextBalanceConnectorId() external view returns (bytes32);\n\n    /**\n     * @dev Tells the address from where the token amounts to execute this task are fetched.\n     * This address must the 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 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 price limit is set\n     */\n    event GasPriceLimitSet(uint256 gasPriceLimit);\n\n    /**\n     * @dev Emitted every time the priority fee limit is set\n     */\n    event PriorityFeeLimitSet(uint256 priorityFeeLimit);\n\n    /**\n     * @dev Emitted every time the transaction cost limit is set\n     */\n    event TxCostLimitSet(uint256 txCostLimit);\n\n    /**\n     * @dev Emitted every time the transaction cost limit percentage is set\n     */\n    event TxCostLimitPctSet(uint256 txCostLimitPct);\n\n    /**\n     * @dev Tells the gas price limit\n     */\n    function gasPriceLimit() external view returns (uint256);\n\n    /**\n     * @dev Tells the priority fee limit\n     */\n    function priorityFeeLimit() external view returns (uint256);\n\n    /**\n     * @dev Tells the transaction cost limit\n     */\n    function txCostLimit() external view returns (uint256);\n\n    /**\n     * @dev Tells the transaction cost limit percentage\n     */\n    function txCostLimitPct() external view returns (uint256);\n\n    /**\n     * @dev Sets the gas price limit\n     * @param newGasPriceLimit New gas price limit to be set\n     */\n    function setGasPriceLimit(uint256 newGasPriceLimit) external;\n\n    /**\n     * @dev Sets the priority fee limit\n     * @param newPriorityFeeLimit New priority fee limit to be set\n     */\n    function setPriorityFeeLimit(uint256 newPriorityFeeLimit) external;\n\n    /**\n     * @dev Sets the transaction cost limit\n     * @param newTxCostLimit New transaction cost limit to be set\n     */\n    function setTxCostLimit(uint256 newTxCostLimit) external;\n\n    /**\n     * @dev Sets the transaction cost limit percentage\n     * @param newTxCostLimitPct New transaction cost limit percentage to be set\n     */\n    function setTxCostLimitPct(uint256 newTxCostLimitPct) 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 has not expired\n     */\n    error TaskTimeLockNotExpired(uint256 expiration, uint256 currentTimestamp);\n\n    /**\n     * @dev The execution period has expired\n     */\n    error TaskTimeLockWaitNextPeriod(uint256 offset, uint256 executionPeriod);\n\n    /**\n     * @dev The execution period is greater than the time-lock delay\n     */\n    error TaskExecutionPeriodGtDelay(uint256 executionPeriod, uint256 delay);\n\n    /**\n     * @dev Emitted every time a new time-lock delay is set\n     */\n    event TimeLockDelaySet(uint256 delay);\n\n    /**\n     * @dev Emitted every time a new expiration timestamp is set\n     */\n    event TimeLockExpirationSet(uint256 expiration);\n\n    /**\n     * @dev Emitted every time a new execution period is set\n     */\n    event TimeLockExecutionPeriodSet(uint256 period);\n\n    /**\n     * @dev Tells the time-lock delay in seconds\n     */\n    function timeLockDelay() external view returns (uint256);\n\n    /**\n     * @dev Tells the time-lock expiration timestamp\n     */\n    function timeLockExpiration() external view returns (uint256);\n\n    /**\n     * @dev Tells the time-lock execution period\n     */\n    function timeLockExecutionPeriod() external view returns (uint256);\n\n    /**\n     * @dev Sets the time-lock delay\n     * @param delay New delay to be set\n     */\n    function setTimeLockDelay(uint256 delay) external;\n\n    /**\n     * @dev Sets the time-lock expiration timestamp\n     * @param expiration New expiration timestamp to be set\n     */\n    function setTimeLockExpiration(uint256 expiration) external;\n\n    /**\n     * @dev Sets the time-lock execution period\n     * @param period New execution period to be set\n     */\n    function setTimeLockExecutionPeriod(uint256 period) 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 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 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 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 (Threshold memory);\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) external view returns (Threshold memory);\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 (Threshold memory);\n\n    /**\n     * @dev Sets a new default threshold config\n     * @param thresholdToken New threshold token to be set\n     * @param thresholdMin New threshold minimum to be set\n     * @param thresholdMax New threshold maximum to be set\n     */\n    function setDefaultTokenThreshold(address thresholdToken, uint256 thresholdMin, uint256 thresholdMax) 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 thresholdMin New custom threshold minimum to be set\n     * @param thresholdMax New custom threshold maximum to be set\n     */\n    function setCustomTokenThreshold(address token, address thresholdToken, uint256 thresholdMin, uint256 thresholdMax)\n        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 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 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 token, 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() external view returns (VolumeLimit memory);\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) external view returns (VolumeLimit memory);\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) external view returns (VolumeLimit memory);\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/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    IGasLimitedTask,\n    ITimeLockedTask,\n    ITokenIndexedTask,\n    ITokenThresholdTask,\n    IVolumeLimitedTask\n{\n\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/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/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "contracts/interfaces/IRelayer.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 Relayer interface\n */\ninterface IRelayer {\n    /**\n     * @dev The token is zero\n     */\n    error RelayerTokenZero();\n\n    /**\n     * @dev The amount is zero\n     */\n    error RelayerAmountZero();\n\n    /**\n     * @dev The collector is zero\n     */\n    error RelayerCollectorZero();\n\n    /**\n     * @dev The recipient is zero\n     */\n    error RelayerRecipientZero();\n\n    /**\n     * @dev The executor is zero\n     */\n    error RelayerExecutorZero();\n\n    /**\n     * @dev Relayer no task given to execute\n     */\n    error RelayerNoTaskGiven();\n\n    /**\n     * @dev Relayer input length mismatch\n     */\n    error RelayerInputLengthMismatch();\n\n    /**\n     * @dev The sender is not allowed\n     */\n    error RelayerExecutorNotAllowed(address sender);\n\n    /**\n     * @dev Trying to execute tasks from different smart vaults\n     */\n    error RelayerMultipleTaskSmartVaults(address task, address taskSmartVault, address expectedSmartVault);\n\n    /**\n     * @dev The task to execute does not have permissions on the associated smart vault\n     */\n    error RelayerTaskDoesNotHavePermissions(address task, address smartVault);\n\n    /**\n     * @dev The smart vault balance plus the available quota are lower than the amount to pay the relayer\n     */\n    error RelayerPaymentInsufficientBalance(address smartVault, uint256 balance, uint256 quota, uint256 amount);\n\n    /**\n     * @dev It failed to send amount minus quota to the smart vault's collector\n     */\n    error RelayerPaymentFailed(address smartVault, uint256 amount, uint256 quota);\n\n    /**\n     * @dev It failed to send owed quota to the smart vault's collector\n     */\n    error RelayerQuotaPaymentFailed(address smartVault, uint256 quota);\n\n    /**\n     * @dev The smart vault balance is lower than the amount to withdraw\n     */\n    error RelayerWithdrawInsufficientBalance(address sender, uint256 balance, uint256 amount);\n\n    /**\n     * @dev It failed to send the amount to the sender\n     */\n    error RelayerWithdrawFailed(address sender, uint256 amount);\n\n    /**\n     * @dev The value sent and the amount differ\n     */\n    error RelayerValueDoesNotMatchAmount(uint256 value, uint256 amount);\n\n    /**\n     * @dev The simulation executed properly\n     */\n    error RelayerSimulationResult(TaskResult[] taskResults);\n\n    /**\n     * @dev Emitted every time an executor is configured\n     */\n    event ExecutorSet(address indexed executor, bool allowed);\n\n    /**\n     * @dev Emitted every time the default collector is set\n     */\n    event DefaultCollectorSet(address indexed collector);\n\n    /**\n     * @dev Emitted every time a collector is set for a smart vault\n     */\n    event SmartVaultCollectorSet(address indexed smartVault, address indexed collector);\n\n    /**\n     * @dev Emitted every time a smart vault's maximum quota is set\n     */\n    event SmartVaultMaxQuotaSet(address indexed smartVault, uint256 maxQuota);\n\n    /**\n     * @dev Emitted every time a smart vault's task is executed\n     */\n    event TaskExecuted(\n        address indexed smartVault,\n        address indexed task,\n        bytes data,\n        bool success,\n        bytes result,\n        uint256 gas,\n        uint256 index\n    );\n\n    /**\n     * @dev Emitted every time some native tokens are deposited for the smart vault's balance\n     */\n    event Deposited(address indexed smartVault, uint256 amount);\n\n    /**\n     * @dev Emitted every time some native tokens are withdrawn from the smart vault's balance\n     */\n    event Withdrawn(address indexed smartVault, uint256 amount);\n\n    /**\n     * @dev Emitted every time some ERC20 tokens are withdrawn from the relayer to an external account\n     */\n    event FundsRescued(address indexed token, address indexed recipient, uint256 amount);\n\n    /**\n     * @dev Emitted every time a smart vault's quota is paid\n     */\n    event QuotaPaid(address indexed smartVault, uint256 amount);\n\n    /**\n     * @dev Emitted every time a smart vault pays for transaction gas to the relayer\n     */\n    event GasPaid(address indexed smartVault, uint256 amount, uint256 quota);\n\n    /**\n     * @dev Task result\n     * @param success Whether the task execution succeeds or not\n     * @param result Result of the task execution\n     */\n    struct TaskResult {\n        bool success;\n        bytes result;\n    }\n\n    /**\n     * @dev Tells the default collector address\n     */\n    function defaultCollector() external view returns (address);\n\n    /**\n     * @dev Tells whether an executor is allowed\n     * @param executor Address of the executor being queried\n     */\n    function isExecutorAllowed(address executor) external view returns (bool);\n\n    /**\n     * @dev Tells the smart vault available balance to relay transactions\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getSmartVaultBalance(address smartVault) external view returns (uint256);\n\n    /**\n     * @dev Tells the custom collector address set for a smart vault\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getSmartVaultCollector(address smartVault) external view returns (address);\n\n    /**\n     * @dev Tells the smart vault maximum quota to be used\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getSmartVaultMaxQuota(address smartVault) external view returns (uint256);\n\n    /**\n     * @dev Tells the smart vault used quota\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getSmartVaultUsedQuota(address smartVault) external view returns (uint256);\n\n    /**\n     * @dev Tells the collector address applicable for a smart vault\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getApplicableCollector(address smartVault) external view returns (address);\n\n    /**\n     * @dev Configures an external executor\n     * @param executor Address of the executor to be set\n     * @param allowed Whether the given executor should be allowed or not\n     */\n    function setExecutor(address executor, bool allowed) external;\n\n    /**\n     * @dev Sets the default collector\n     * @param collector Address of the new default collector to be set\n     */\n    function setDefaultCollector(address collector) external;\n\n    /**\n     * @dev Sets a custom collector for a smart vault\n     * @param smartVault Address of smart vault to set a collector for\n     * @param collector Address of the collector to be set for the given smart vault\n     */\n    function setSmartVaultCollector(address smartVault, address collector) external;\n\n    /**\n     * @dev Sets a maximum quota for a smart vault\n     * @param smartVault Address of smart vault to set a maximum quota for\n     * @param maxQuota Maximum quota to be set for the given smart vault\n     */\n    function setSmartVaultMaxQuota(address smartVault, uint256 maxQuota) external;\n\n    /**\n     * @dev Deposits native tokens for a given smart vault\n     * @param smartVault Address of smart vault to deposit balance for\n     * @param amount Amount of native tokens to be deposited, must match msg.value\n     */\n    function deposit(address smartVault, uint256 amount) external payable;\n\n    /**\n     * @dev Withdraws native tokens from a given smart vault\n     * @param amount Amount of native tokens to be withdrawn\n     */\n    function withdraw(uint256 amount) external;\n\n    /**\n     * @dev Executes a list of tasks\n     * @param tasks Addresses of the tasks to execute\n     * @param data List of calldata to execute each of the given tasks\n     * @param continueIfFailed Whether the execution should fail in case one of the tasks fail\n     */\n    function execute(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external;\n\n    /**\n     * @dev Simulates an execution.\n     * WARNING: THIS METHOD IS MEANT TO BE USED AS A VIEW FUNCTION\n     * This method will always revert. Successful results or task execution errors are returned as\n     * `RelayerSimulationResult` errors. Any other error should be treated as failure.\n     * @param tasks Addresses of the tasks to simulate the execution of\n     * @param data List of calldata to simulate each of the given tasks execution\n     * @param continueIfFailed Whether the simulation should fail in case one of the tasks execution fails\n     */\n    function simulate(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external;\n\n    /**\n     * @dev Withdraw ERC20 tokens to an external account. To be used in case of accidental token transfers.\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 rescueFunds(address token, address recipient, uint256 amount) external;\n}\n"
      },
      "contracts/Relayer.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/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nimport '@mimic-fi/v3-smart-vault/contracts/interfaces/ISmartVault.sol';\nimport '@mimic-fi/v3-tasks/contracts/interfaces/ITask.sol';\n\nimport './interfaces/IRelayer.sol';\n\n/**\n * @title Relayer\n * @dev Relayer used to execute relayed tasks\n */\ncontract Relayer is IRelayer, Ownable {\n    using SafeERC20 for IERC20;\n\n    // Gas amount charged to cover base costs\n    uint256 public constant BASE_GAS = 70.5e3;\n\n    // Default collector address\n    address public override defaultCollector;\n\n    // List of allowed executors\n    mapping (address => bool) public override isExecutorAllowed;\n\n    // List of native token balances per smart vault\n    mapping (address => uint256) public override getSmartVaultBalance;\n\n    // List of custom collector address per smart vault\n    mapping (address => address) public override getSmartVaultCollector;\n\n    // List of maximum quota to be used per smart vault\n    mapping (address => uint256) public override getSmartVaultMaxQuota;\n\n    // List of used quota per smart vault\n    mapping (address => uint256) public override getSmartVaultUsedQuota;\n\n    /**\n     * @dev Creates a new Relayer contract\n     * @param executor Address of the executor that will be allowed to call the relayer\n     * @param collector Address of the default collector to be set\n     * @param owner Address that will own the fee collector\n     */\n    constructor(address executor, address collector, address owner) {\n        _setExecutor(executor, true);\n        _setDefaultCollector(collector);\n        _transferOwnership(owner);\n    }\n\n    /**\n     * @dev Tells the collector address applicable for a smart vault\n     * @param smartVault Address of the smart vault being queried\n     */\n    function getApplicableCollector(address smartVault) public view override returns (address) {\n        address customCollector = getSmartVaultCollector[smartVault];\n        return customCollector != address(0) ? customCollector : defaultCollector;\n    }\n\n    /**\n     * @dev Configures an external executor\n     * @param executor Address of the executor to be set\n     * @param allowed Whether the given executor should be allowed or not\n     */\n    function setExecutor(address executor, bool allowed) external override onlyOwner {\n        _setExecutor(executor, allowed);\n    }\n\n    /**\n     * @dev Sets the default collector\n     * @param collector Address of the new default collector to be set\n     */\n    function setDefaultCollector(address collector) external override onlyOwner {\n        _setDefaultCollector(collector);\n    }\n\n    /**\n     * @dev Sets a custom collector for a smart vault\n     * @param smartVault Address of smart vault to set a collector for\n     * @param collector Address of the collector to be set for the given smart vault\n     */\n    function setSmartVaultCollector(address smartVault, address collector) external override onlyOwner {\n        getSmartVaultCollector[smartVault] = collector;\n        emit SmartVaultCollectorSet(smartVault, collector);\n    }\n\n    /**\n     * @dev Sets a maximum quota for a smart vault\n     * @param smartVault Address of smart vault to set a maximum quota for\n     * @param maxQuota Maximum quota to be set for the given smart vault\n     */\n    function setSmartVaultMaxQuota(address smartVault, uint256 maxQuota) external override onlyOwner {\n        getSmartVaultMaxQuota[smartVault] = maxQuota;\n        emit SmartVaultMaxQuotaSet(smartVault, maxQuota);\n    }\n\n    /**\n     * @dev Deposits native tokens for a given smart vault. First, it will pay part of the quota if any.\n     * @param smartVault Address of smart vault to deposit balance for\n     * @param amount Amount of native tokens to be deposited, must match msg.value\n     */\n    function deposit(address smartVault, uint256 amount) external payable override {\n        if (msg.value != amount) revert RelayerValueDoesNotMatchAmount(msg.value, amount);\n        uint256 amountPaid = _payQuota(smartVault, amount);\n        uint256 toDeposit = amount - amountPaid;\n        getSmartVaultBalance[smartVault] += toDeposit;\n        emit Deposited(smartVault, toDeposit);\n    }\n\n    /**\n     * @dev Withdraws native tokens from the sender\n     * @param amount Amount of native tokens to be withdrawn\n     */\n    function withdraw(uint256 amount) external override {\n        uint256 balance = getSmartVaultBalance[msg.sender];\n        if (amount > balance) revert RelayerWithdrawInsufficientBalance(msg.sender, balance, amount);\n\n        getSmartVaultBalance[msg.sender] = balance - amount;\n        emit Withdrawn(msg.sender, amount);\n\n        (bool success, ) = payable(msg.sender).call{ value: amount }('');\n        if (!success) revert RelayerWithdrawFailed(msg.sender, amount);\n    }\n\n    /**\n     * @dev Executes a list of tasks\n     * @param tasks Addresses of the tasks to execute\n     * @param data List of calldata to execute each of the given tasks\n     * @param continueIfFailed Whether the execution should fail in case one of the tasks fail\n     */\n    function execute(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external override {\n        _execute(tasks, data, continueIfFailed);\n    }\n\n    /**\n     * @dev Simulates an execution.\n     * WARNING: THIS METHOD IS MEANT TO BE USED AS A VIEW FUNCTION\n     * This method will always revert. Successful results or task execution errors are returned as\n     * `RelayerSimulationResult` errors. Any other error should be treated as failure.\n     * @param tasks Addresses of the tasks to simulate the execution of\n     * @param data List of calldata to simulate each of the given tasks execution\n     * @param continueIfFailed Whether the simulation should fail in case one of the tasks execution fails\n     */\n    function simulate(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external override {\n        revert RelayerSimulationResult(_execute(tasks, data, continueIfFailed));\n    }\n\n    /**\n     * @dev Withdraw ERC20 tokens to an external account. To be used in case of accidental token transfers.\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 rescueFunds(address token, address recipient, uint256 amount) external override onlyOwner {\n        if (token == address(0)) revert RelayerTokenZero();\n        if (recipient == address(0)) revert RelayerRecipientZero();\n        if (amount == 0) revert RelayerAmountZero();\n\n        IERC20(token).safeTransfer(recipient, amount);\n        emit FundsRescued(token, recipient, amount);\n    }\n\n    /**\n     * @dev Configures an external executor\n     * @param executor Address of the executor to be set\n     * @param allowed Whether the given executor should be allowed or not\n     */\n    function _setExecutor(address executor, bool allowed) internal {\n        if (executor == address(0)) revert RelayerExecutorZero();\n        isExecutorAllowed[executor] = allowed;\n        emit ExecutorSet(executor, allowed);\n    }\n\n    /**\n     * @dev Sets the default collector\n     * @param collector Default fee collector to be set\n     */\n    function _setDefaultCollector(address collector) internal {\n        if (collector == address(0)) revert RelayerCollectorZero();\n        defaultCollector = collector;\n        emit DefaultCollectorSet(collector);\n    }\n\n    /**\n     * @dev Executes a list of tasks\n     * @param tasks Addresses of the tasks to execute\n     * @param data List of calldata to execute each of the given tasks\n     * @param continueIfFailed Whether the execution should fail in case one of the tasks fail\n     * @return taskResults List of task execution results\n     */\n    function _execute(address[] memory tasks, bytes[] memory data, bool continueIfFailed)\n        internal\n        returns (TaskResult[] memory taskResults)\n    {\n        if (!isExecutorAllowed[msg.sender]) revert RelayerExecutorNotAllowed(msg.sender);\n        if (tasks.length == 0) revert RelayerNoTaskGiven();\n        if (tasks.length != data.length) revert RelayerInputLengthMismatch();\n\n        uint256 totalGasUsed = BASE_GAS;\n        address smartVault = ITask(tasks[0]).smartVault();\n        taskResults = new TaskResult[](tasks.length);\n\n        for (uint256 i = 0; i < tasks.length; i++) {\n            uint256 initialGas = gasleft();\n            address task = tasks[i];\n\n            // Note the line below prevents `task` from being an EOA or a contract that does not implement ITask (e.g. a token contract)\n            address taskSmartVault = ITask(task).smartVault();\n            if (taskSmartVault != smartVault) revert RelayerMultipleTaskSmartVaults(task, taskSmartVault, smartVault);\n\n            // Note the validation below is the only one made on task, by checking that the smart vault that will pay for the gas is somehow related to it.\n            // This check is critical since the smart vault is not referenced again inside this function.\n            bool hasPermissions = ISmartVault(smartVault).hasPermissions(task);\n            if (!hasPermissions) revert RelayerTaskDoesNotHavePermissions(task, smartVault);\n\n            // Note if `task` were an EOA the line below would succeed, resulting in a false positive. This is prevented a few lines above by making sure `task` is a contract that implements ITask.\n            // solhint-disable-next-line avoid-low-level-calls\n            (bool success, bytes memory result) = task.call(data[i]);\n            taskResults[i] = TaskResult(success, result);\n            uint256 gasUsed = initialGas - gasleft();\n            // Does not charge gas if the task was not executed successfully\n            if (success) totalGasUsed += gasUsed;\n\n            emit TaskExecuted(smartVault, task, data[i], success, result, gasUsed, i);\n            if (!success && !continueIfFailed) break;\n        }\n\n        // Does not charge gas if no task was executed successfully\n        if (totalGasUsed == BASE_GAS) return taskResults;\n\n        uint256 totalGasCost = totalGasUsed * tx.gasprice;\n        _payTransactionGasToRelayer(smartVault, totalGasCost);\n    }\n\n    /**\n     * @dev Pays transaction gas to the relayer withdrawing native tokens from a given smart vault\n     * @param smartVault Address of smart vault to withdraw balance of\n     * @param amount Amount of native tokens to be withdrawn\n     */\n    function _payTransactionGasToRelayer(address smartVault, uint256 amount) internal {\n        uint256 balance = getSmartVaultBalance[smartVault];\n        uint256 maxQuota = getSmartVaultMaxQuota[smartVault];\n        uint256 usedQuota = getSmartVaultUsedQuota[smartVault];\n        uint256 availableQuota = usedQuota >= maxQuota ? 0 : (maxQuota - usedQuota);\n        bool hasEnoughBalance = amount <= balance + availableQuota;\n        if (!hasEnoughBalance) revert RelayerPaymentInsufficientBalance(smartVault, balance, availableQuota, amount);\n\n        uint256 valueToSend;\n        uint256 quota = 0;\n        if (balance >= amount) {\n            getSmartVaultBalance[smartVault] = balance - amount;\n            valueToSend = amount;\n        } else {\n            quota = amount - balance;\n            getSmartVaultBalance[smartVault] = 0;\n            getSmartVaultUsedQuota[smartVault] = usedQuota + quota;\n            valueToSend = balance;\n        }\n\n        if (valueToSend > 0) {\n            (bool paySuccess, ) = getApplicableCollector(smartVault).call{ value: valueToSend }('');\n            if (!paySuccess) revert RelayerPaymentFailed(smartVault, amount, quota);\n        }\n        emit GasPaid(smartVault, amount, quota);\n    }\n\n    /**\n     * @dev Pays part of the quota for a given smart vault, if applicable\n     * @param smartVault Address of smart vault to pay quota for\n     * @param toDeposit Amount of native tokens to be deposited for the smart vault\n     * @return quotaPaid Amount of native tokens used to pay the quota\n     */\n    function _payQuota(address smartVault, uint256 toDeposit) internal returns (uint256 quotaPaid) {\n        uint256 usedQuota = getSmartVaultUsedQuota[smartVault];\n        if (usedQuota == 0) return 0;\n\n        if (toDeposit > usedQuota) {\n            getSmartVaultUsedQuota[smartVault] = 0;\n            quotaPaid = usedQuota;\n        } else {\n            getSmartVaultUsedQuota[smartVault] = usedQuota - toDeposit;\n            quotaPaid = toDeposit;\n        }\n\n        (bool paySuccess, ) = getApplicableCollector(smartVault).call{ value: quotaPaid }('');\n        if (!paySuccess) revert RelayerQuotaPaymentFailed(smartVault, quotaPaid);\n        emit QuotaPaid(smartVault, quotaPaid);\n    }\n}\n"
      },
      "contracts/test/TaskMock.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ncontract TaskMock {\n    event Succeeded();\n\n    address public smartVault;\n\n    constructor(address _smartVault) {\n        smartVault = _smartVault;\n    }\n\n    function succeed() external returns (uint256) {\n        emit Succeeded();\n        return 1;\n    }\n\n    function fail() external pure {\n        revert('TASK_FAILED');\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}