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