More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
28838484 | 10 days ago | 0.00171 ETH | ||||
28609827 | 16 days ago | 0.019 ETH | ||||
28609682 | 16 days ago | 0.019 ETH | ||||
28431575 | 20 days ago | 0.00000057 ETH | ||||
28376867 | 21 days ago | 0 ETH | ||||
27817791 | 34 days ago | 0.0095 ETH | ||||
27795138 | 35 days ago | 0.0001273 ETH | ||||
27423201 | 43 days ago | 0.000057 ETH | ||||
27409863 | 43 days ago | 0.00038 ETH | ||||
27232095 | 48 days ago | 0.00001577 ETH | ||||
27232060 | 48 days ago | 0.00001577 ETH | ||||
27105172 | 51 days ago | 0.000095 ETH | ||||
27017072 | 53 days ago | 0.000855 ETH | ||||
26876559 | 56 days ago | 0.00057 ETH | ||||
26829209 | 57 days ago | 0.0285 ETH | ||||
26582582 | 63 days ago | 0.0001368 ETH | ||||
26377380 | 67 days ago | 0.00125115 ETH | ||||
26335520 | 68 days ago | 0.0001425 ETH | ||||
26045956 | 75 days ago | 0.000361 ETH | ||||
25992073 | 76 days ago | 0.00019 ETH | ||||
25886620 | 79 days ago | 0.00038 ETH | ||||
25886483 | 79 days ago | 0.00038 ETH | ||||
25874030 | 79 days ago | 0.005225 ETH | ||||
25873967 | 79 days ago | 0.005225 ETH | ||||
25869587 | 79 days ago | 0.0002755 ETH |
Loading...
Loading
Minimal Proxy Contract for 0x167a871142494b86007761d12735017ceb227ed8
Contract Name:
Depositor
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 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 '@openzeppelin/contracts/utils/Address.sol'; import '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol'; import '@mimic-fi/v3-helpers/contracts/utils/Denominations.sol'; import '../Task.sol'; import '../interfaces/primitives/IDepositor.sol'; /** * @title Depositor * @dev Task that can be used as the origin to start any workflow */ contract Depositor is IDepositor, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('DEPOSITOR'); /** * @dev Deposit config. Only used in the initializer. */ struct DepositConfig { TaskConfig taskConfig; } /** * @dev Initializes the depositor * @param config Deposit config */ function initialize(DepositConfig memory config) external virtual initializer { __Depositor_init(config); } /** * @dev Initializes the depositor. It does call upper contracts initializers. * @param config Deposit config */ function __Depositor_init(DepositConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __Depositor_init_unchained(config); } /** * @dev Initializes the depositor. It does not call upper contracts initializers. * @param config Deposit config */ function __Depositor_init_unchained(DepositConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Tells the address from where the token amounts to execute this task are fetched */ function getTokensSource() public view virtual override(IBaseTask, BaseTask) returns (address) { return address(this); } /** * @dev Tells the balance of the depositor for a given token * @param token Address of the token being queried */ function getTaskAmount(address token) public view virtual override(IBaseTask, BaseTask) returns (uint256) { return ERC20Helpers.balanceOf(token, getTokensSource()); } /** * @dev It allows receiving native token transfers */ receive() external payable { if (msg.value == 0) revert TaskValueZero(); } /** * @dev Execute Depositor */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeDepositor(token, amount); if (Denominations.isNativeToken(token)) { Address.sendValue(payable(smartVault), amount); } else { ERC20Helpers.approve(token, smartVault, amount); ISmartVault(smartVault).collect(token, getTokensSource(), amount); } _afterDepositor(token, amount); } /** * @dev Before depositor hook */ function _beforeDepositor(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After depositor hook */ function _afterDepositor(address token, uint256 amount) internal virtual { _increaseBalanceConnector(token, amount); _afterTask(token, amount); } /** * @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, address p3, uint256 p4) internal pure returns (uint256[] memory r) { r = new uint256[](4); r[0] = uint256(uint160(p1)); r[1] = p2; r[2] = uint256(uint160(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 1inch V5 connector interface */ interface IOneInchV5Connector { /** * @dev The token in is the same as the token out */ error OneInchV5SwapSameToken(address token); /** * @dev The amount out is lower than the minimum amount out */ error OneInchV5BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error OneInchV5BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the reference to 1inch aggregation router v5 */ function oneInchV5Router() external view returns (address); /** * @dev Executes a token swap in 1Inch V5 * @param tokenIn Token to be sent * @param tokenOut Token to be received * @param amountIn Amount of token in to be swapped * @param minAmountOut Minimum amount of token out willing to receive * @param data Calldata to be sent to the 1inch aggregation router */ function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data) external returns (uint256 amountOut); }
// 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 Axelar connector interface */ interface IAxelarConnector { /** * @dev The recipient address is zero */ error AxelarBridgeRecipientZero(); /** * @dev The source and destination chains are the same */ error AxelarBridgeSameChain(uint256 chainId); /** * @dev The chain ID is not supported */ error AxelarBridgeUnknownChainId(uint256 chainId); /** * @dev The post token balance is lower than the previous token balance minus the amount bridged */ error AxelarBridgeBadPostTokenBalance(uint256 postBalance, uint256 preBalance, uint256 amount); /** * @dev Tells the reference to the Axelar gateway of the source chain */ function axelarGateway() external view returns (address); /** * @dev Executes a bridge of assets using Axelar * @param chainId ID of the destination chain * @param token Address of the token to be bridged * @param amount Amount of tokens to be bridged * @param recipient Address that will receive the tokens on the destination chain */ function execute(uint256 chainId, 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; /** * @title Balancer pool connector interface */ interface IBalancerV2PoolConnector { /** * @dev The given input length is invalid or do not match */ error BalancerV2InvalidInputLength(); /** * @dev The given tokens out length is not the expected one */ error BalancerV2InvalidTokensOutLength(); /** * @dev The given pool ID and bpt in do not match on Balancer vault */ error BalancerV2InvalidPoolId(bytes32 poolId, address bpt); /** * @dev The given token does not belong to the pool */ error BalancerV2InvalidToken(bytes32 poolId, address token); /** * @dev The post balance of the token in unexpected */ error BalancerV2BadTokenInBalance(uint256 postBalance, uint256 preBalance, uint256 amountIn); /** * @dev The post balance of the token out is unexpected */ error BalancerV2BadTokenOutBalance(uint256 postBalance, uint256 preBalance); /** * @dev The resulting amount out is lower than the expected min amount out */ error BalancerV2BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev Tells the reference to Balancer v2 vault */ function balancerV2Vault() external view returns (address); /** * @dev Adds liquidity to a Balancer pool * @param poolId Balancer pool ID * @param tokenIn Address of the token to join the Balancer pool * @param amountIn Amount of tokens to join the Balancer pool * @param minAmountOut Minimum amount of pool tokens expected to receive after join */ function join(bytes32 poolId, address tokenIn, uint256 amountIn, uint256 minAmountOut) external returns (uint256 amountOut); /** * @dev Removes liquidity from a Balancer pool * @param tokenIn Address of the pool to exit * @param amountIn Amount of pool tokens to exit * @param tokensOut List of addresses of tokens in the pool * @param minAmountsOut List of min amounts out to be expected for each pool token */ function exit(address tokenIn, uint256 amountIn, address[] memory tokensOut, uint256[] memory minAmountsOut) external returns (uint256[] memory amountsOut); }
// 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 Balancer v2 swap connector interface */ interface IBalancerV2SwapConnector { /** * @dev The input length mismatch */ error BalancerV2InputLengthMismatch(); /** * @dev The token in is the same as the token out */ error BalancerV2SwapSameToken(address token); /** * @dev The pool does not exist on the Balancer vault */ error BalancerV2InvalidPool(bytes32 poolId); /** * @dev The requested tokens do not belong to the pool */ error BalancerV2InvalidPoolTokens(bytes32 poolId, address tokenA, address tokenB); /** * @dev The returned amount in is not equal to the requested amount in */ error BalancerV2InvalidAmountIn(int256 amountIn); /** * @dev The returned amount out is greater than or equal to zero */ error BalancerV2InvalidAmountOut(int256 amountOut); /** * @dev The amount out is lower than the minimum amount out */ error BalancerV2BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error BalancerV2BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the reference to Balancer v2 vault */ function balancerV2Vault() external view returns (address); /** * @dev Executes a token swap in Balancer V2 * @param tokenIn Token being sent * @param tokenOut Token being received * @param amountIn Amount of tokenIn being swapped * @param minAmountOut Minimum amount of tokenOut willing to receive * @param poolId Pool ID to be used * @param hopPoolsIds Optional list of hop-pools between tokenIn and tokenOut, only used for multi-hops * @param hopTokens Optional list of hop-tokens between tokenIn and tokenOut, only used for multi-hops */ function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes32 poolId, bytes32[] memory hopPoolsIds, address[] memory hopTokens ) external returns (uint256 amountOut); }
// 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'; interface IBalancerV2Vault { function getPool(bytes32 poolId) external view returns (address, uint256); function getPoolTokens(bytes32 poolId) external view returns (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock); struct JoinPoolRequest { IERC20[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } function joinPool(bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request) external payable; struct ExitPoolRequest { IERC20[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function exitPool(bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request) external; enum SwapKind { GIVEN_IN, GIVEN_OUT } struct SingleSwap { bytes32 poolId; SwapKind kind; address assetIn; address assetOut; uint256 amount; bytes userData; } struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline) external payable returns (uint256); struct BatchSwapStep { bytes32 poolId; uint256 assetInIndex; uint256 assetOutIndex; uint256 amount; bytes userData; } function batchSwap( SwapKind kind, BatchSwapStep[] memory swaps, address[] memory assets, FundManagement memory funds, int256[] memory limits, uint256 deadline ) external payable returns (int256[] memory); }
// 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 Connext connector interface * @dev Interfaces with Connext to bridge tokens */ interface IConnextConnector { /** * @dev The recipient address is zero */ error ConnextBridgeRecipientZero(); /** * @dev The source and destination chains are the same */ error ConnextBridgeSameChain(uint256 chainId); /** * @dev The chain ID is not supported */ error ConnextBridgeUnknownChainId(uint256 chainId); /** * @dev The relayer fee is greater than the amount to be bridged */ error ConnextBridgeRelayerFeeGtAmount(uint256 relayerFee, uint256 amount); /** * @dev The minimum amount out is greater than the amount to be bridged minus the relayer fee */ error ConnextBridgeMinAmountOutTooBig(uint256 minAmountOut, uint256 amount, uint256 relayerFee); /** * @dev The post token balance is lower than the previous token balance minus the amount bridged */ error ConnextBridgeBadPostTokenBalance(uint256 postBalance, uint256 preBalance, uint256 amount); /** * @dev Tells the reference to the Connext contract of the source chain */ function connext() external view returns (address); /** * @dev Executes a bridge of assets using Connext * @param chainId ID of the destination chain * @param token Address of the token to be bridged * @param amount Amount of tokens to be bridged * @param minAmountOut Min amount of tokens to receive on the destination chain after relayer fees and slippage * @param recipient Address that will receive the tokens on the destination chain * @param relayerFee Fee to be paid to the relayer */ function execute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, uint256 relayerFee ) 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 Convex connector interface */ interface IConvexConnector { /** * @dev Missing Convex pool for the requested Curve pool */ error ConvexCvxPoolNotFound(address curvePool); /** * @dev Failed to deposit tokens into the Convex booster */ error ConvexBoosterDepositFailed(uint256 poolId, uint256 amount); /** * @dev Failed to withdraw tokens from Convex pool */ error ConvexCvxPoolWithdrawFailed(address cvxPool, uint256 amount); /** * @dev Tells the reference to the Convex booster */ function booster() external view returns (address); /** * @dev Finds the Curve pool address associated to a Convex pool */ function getCurvePool(address cvxPool) external view returns (address); /** * @dev Finds the Curve pool address associated to a Convex pool */ function getCvxPool(address curvePool) external view returns (address); /** * @dev Claims Convex pool rewards for a Curve pool */ function claim(address cvxPool) external returns (address[] memory tokens, uint256[] memory amounts); /** * @dev Deposits Curve pool tokens into Convex * @param curvePool Address of the Curve pool to join Convex * @param amount Amount of Curve pool tokens to be deposited into Convex */ function join(address curvePool, uint256 amount) external returns (uint256); /** * @dev Withdraws Curve pool tokens from Convex * @param cvxPool Address of the Convex pool to exit from Convex * @param amount Amount of Convex tokens to be withdrawn */ function exit(address cvxPool, uint256 amount) external returns (uint256); }
// 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 Curve 2CRV connector interface */ interface ICurve2CrvConnector { /** * @dev Failed to find the token in the 2CRV pool */ error Curve2CrvTokenNotFound(address pool, address token); /** * @dev Token decimals exceed 18 */ error Curve2CrvTokenDecimalsAbove18(address token, uint256 decimals); /** * @dev The slippage is above one */ error Curve2CrvSlippageAboveOne(uint256 slippage); /** * @dev Adds liquidity to the 2CRV pool * @param pool Address of the 2CRV pool to join * @param tokenIn Address of the token to join the 2CRV pool * @param amountIn Amount of tokens to join the 2CRV pool * @param slippage Slippage value to be used to compute the desired min amount out of pool tokens */ function join(address pool, address tokenIn, uint256 amountIn, uint256 slippage) external returns (uint256); /** * @dev Removes liquidity from 2CRV pool * @param pool Address of the 2CRV pool to exit * @param amountIn Amount of pool tokens to exit from the 2CRV pool * @param tokenOut Address of the token to exit the pool * @param slippage Slippage value to be used to compute the desired min amount out of tokens */ function exit(address pool, uint256 amountIn, address tokenOut, uint256 slippage) external returns (uint256 amountOut); }
// 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 ERC4626 connector interface */ interface IERC4626Connector { /** * @dev The token is not the underlying token of the ERC4626 */ error ERC4626InvalidToken(address token, address underlying); /** * @dev The amount deposited is lower than the expected amount */ error ERC4626BadSharesOut(uint256 shares, uint256 minSharesOut); /** * @dev The amount redeemed is lower than the expected amount */ error ERC4626BadAssetsOut(uint256 assets, uint256 minAssetsOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error ERC4626BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the underlying token of an ERC4626 */ function getToken(address erc4626) external view returns (address); /** * @dev Deposits assets to the underlying ERC4626 * @param erc4626 Address of the ERC4626 to join * @param tokenIn Address of the token to join the ERC4626 * @param assets Amount of assets to be deposited * @param minSharesOut Minimum amount of shares willing to receive */ function join(address erc4626, address tokenIn, uint256 assets, uint256 minSharesOut) external returns (address tokenOut, uint256 shares); /** * @dev Withdraws assets from the underlying ERC4626 * @param erc4626 Address of the ERC4626 to exit * @param shares Amount of shares to be redeemed * @param minAssetsOut Minimum amount of assets willing to receive */ function exit(address erc4626, uint256 shares, uint256 minAssetsOut) external returns (address token, uint256 assets); }
// 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 Hop connector interface */ interface IHopBridgeConnector { /** * @dev The source and destination chains are the same */ error HopBridgeSameChain(uint256 chainId); /** * @dev The bridge operation is not supported */ error HopBridgeOpNotSupported(); /** * @dev The recipient address is zero */ error HopBridgeRecipientZero(); /** * @dev The relayer was sent when not needed */ error HopBridgeRelayerNotNeeded(); /** * @dev The deadline was sent when not needed */ error HopBridgeDeadlineNotNeeded(); /** * @dev The deadline is in the past */ error HopBridgePastDeadline(uint256 deadline, uint256 currentTimestamp); /** * @dev The post token balance is lower than the previous token balance minus the amount bridged */ error HopBridgeBadPostTokenBalance(uint256 postBalance, uint256 preBalance, uint256 amount); /** * @dev Tells the reference to the wrapped native token address */ function wrappedNativeToken() external view returns (address); /** * @dev Executes a bridge of assets using Hop Exchange * @param chainId ID of the destination chain * @param token Address of the token to be bridged * @param amount Amount of tokens to be bridged * @param minAmountOut Minimum amount of tokens willing to receive on the destination chain * @param recipient Address that will receive the tokens on the destination chain * @param bridge Address of the bridge component (i.e. hopBridge or hopAMM) * @param deadline Deadline to be used when bridging to L2 in order to swap the corresponding hToken * @param relayer Only used when transferring from L1 to L2 if a 3rd party is relaying the transfer on the user's behalf * @param fee Fee to be sent to the bridge based on the source and destination chain (i.e. relayerFee or bonderFee) */ function execute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, address bridge, uint256 deadline, address relayer, uint256 fee ) 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 IHopL2Amm { function hToken() external view returns (address); function exchangeAddress() external view returns (address); /** * @notice To send funds L2->L1 or L2->L2, call the swapAndSend method on the L2 AMM Wrapper contract * @dev Do not set destinationAmountOutMin and destinationDeadline when sending to L1 because there is no AMM on L1, * otherwise the calculated transferId will be invalid and the transfer will be unbondable. These parameters should * be set to 0 when sending to L1. * @param amount is the amount the user wants to send plus the Bonder fee */ function swapAndSend( uint256 chainId, address recipient, uint256 amount, uint256 bonderFee, uint256 amountOutMin, uint256 deadline, uint256 destinationAmountOutMin, uint256 destinationDeadline ) external payable; }
// 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 Hop swap connector interface */ interface IHopSwapConnector { /** * @dev The dex address is zero */ error HopDexAddressZero(); /** * @dev The token in is the same as the token out */ error HopSwapSameToken(address token); /** * @dev The amount out is lower than the minimum amount out */ error HopBadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the pre token in balance minus the amount in */ error HopBadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Executes a token swap in Hop * @param tokenIn Token being sent * @param tokenOut Token being received * @param amountIn Amount of tokenIn being swapped * @param minAmountOut Minimum amount of tokenOut willing to receive * @param hopDexAddress Address of the Hop dex to be used */ function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address hopDexAddress) external returns (uint256 amountOut); }
// 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 Paraswap V5 connector interface */ interface IParaswapV5Connector { /** * @dev The token in is the same as the token out */ error ParaswapV5SwapSameToken(address token); /** * @dev The amount out is lower than the minimum amount out */ error ParaswapV5BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error ParaswapV5BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the reference to Paraswap V5 Augustus swapper */ function paraswapV5Augustus() external view returns (address); /** * @dev Executes a token swap in Paraswap V5 * @param tokenIn Token being sent * @param tokenOut Token being received * @param amountIn Amount of tokenIn being swapped * @param minAmountOut Minimum amount of tokenOut willing to receive * @param data Calldata to be sent to the Augusuts swapper */ function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data) external returns (uint256 amountOut); }
// 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 Uniswap V2 connector interface */ interface IUniswapV2Connector { /** * @dev The token in is the same as the token out */ error UniswapV2SwapSameToken(address token); /** * @dev The pool does not exist */ error UniswapV2InvalidPool(address tokenA, address tokenB); /** * @dev The amount out is lower than the minimum amount out */ error UniswapV2BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error UniswapV2BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the reference to UniswapV2 router */ function uniswapV2Router() external view returns (address); /** * @dev Executes a token swap in Uniswap V2 * @param tokenIn Token being sent * @param tokenOut Token being received * @param amountIn Amount of tokenIn being swapped * @param minAmountOut Minimum amount of tokenOut willing to receive * @param hopTokens Optional list of hop-tokens between tokenIn and tokenOut, only used for multi-hops */ function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address[] memory hopTokens ) external returns (uint256 amountOut); }
// 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 Uniswap V3 connector interface */ interface IUniswapV3Connector { /** * @dev The input length mismatch */ error UniswapV3InputLengthMismatch(); /** * @dev The token in is the same as the token out */ error UniswapV3SwapSameToken(address token); /** * @dev A pool with the given tokens and fee does not exist */ error UniswapV3InvalidPoolFee(address token0, address token1, uint24 fee); /** * @dev The amount out is lower than the minimum amount out */ error UniswapV3BadAmountOut(uint256 amountOut, uint256 minAmountOut); /** * @dev The post token in balance is lower than the previous token in balance minus the amount in */ error UniswapV3BadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn); /** * @dev Tells the reference to UniswapV3 router */ function uniswapV3Router() external view returns (address); /** * @dev Executes a token swap in Uniswap V3 * @param tokenIn Token being sent * @param tokenOut Token being received * @param amountIn Amount of tokenIn being swapped * @param minAmountOut Minimum amount of tokenOut willing to receive * @param fee Fee to be used * @param hopTokens Optional list of hop-tokens between tokenIn and tokenOut, only used for multi-hops * @param hopFees Optional list of hop-fees between tokenIn and tokenOut, only used for multi-hops */ function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint24 fee, address[] memory hopTokens, uint24[] memory hopFees ) external returns (uint256 amountOut); }
// 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 Wormhole connector interface */ interface IWormholeConnector { /** * @dev The recipient address is zero */ error WormholeBridgeRecipientZero(); /** * @dev The source and destination chains are the same */ error WormholeBridgeSameChain(uint256 chainId); /** * @dev The chain ID is not supported */ error WormholeBridgeUnknownChainId(uint256 chainId); /** * @dev The relayer fee is greater than the amount to be bridged */ error WormholeBridgeRelayerFeeGtAmount(uint256 relayerFee, uint256 amount); /** * @dev The minimum amount out is greater than the amount to be bridged minus the relayer fee */ error WormholeBridgeMinAmountOutTooBig(uint256 minAmountOut, uint256 amount, uint256 relayerFee); /** * @dev The post token balance is lower than the previous token balance minus the amount bridged */ error WormholeBridgeBadPostTokenBalance(uint256 postBalance, uint256 preBalance, uint256 amount); /** * @dev Tells the reference to the Wormhole's CircleRelayer contract of the source chain */ function wormholeCircleRelayer() external view returns (address); /** * @dev Executes a bridge of assets using Wormhole's CircleRelayer integration * @param chainId ID of the destination chain * @param token Address of the token to be bridged * @param amount Amount of tokens to be bridged * @param minAmountOut Minimum amount of tokens willing to receive on the destination chain after relayer fees * @param recipient Address that will receive the tokens on the destination chain */ function execute(uint256 chainId, address token, uint256 amount, uint256 minAmountOut, 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; /** * @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: MIT pragma solidity ^0.8.0; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; contract TokenMock is ERC20 { uint8 internal _decimals; constructor(string memory symbol, uint8 dec) ERC20(symbol, symbol) { _decimals = dec; } function mint(address account, uint256 amount) external { _mint(account, amount); } function decimals() public view override returns (uint8) { return _decimals; } }
// 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 BytesHelpers * @dev Provides a list of Bytes helper methods */ library BytesHelpers { /** * @dev The length is shorter than start plus 32 */ error BytesOutOfBounds(uint256 start, uint256 length); /** * @dev Concatenates an address to a bytes array */ function concat(bytes memory self, address value) internal pure returns (bytes memory) { return abi.encodePacked(self, value); } /** * @dev Concatenates an uint24 to a bytes array */ function concat(bytes memory self, uint24 value) internal pure returns (bytes memory) { return abi.encodePacked(self, value); } /** * @dev Decodes a bytes array into an uint256 */ function toUint256(bytes memory self) internal pure returns (uint256) { return toUint256(self, 0); } /** * @dev Reads an uint256 from a bytes array starting at a given position */ function toUint256(bytes memory self, uint256 start) internal pure returns (uint256 result) { if (self.length < start + 32) revert BytesOutOfBounds(start, self.length); assembly { result := mload(add(add(self, 0x20), start)) } } }
// 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.forceApprove(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; /** * @dev Relayer interface */ interface IRelayer { /** * @dev The token is zero */ error RelayerTokenZero(); /** * @dev The amount is zero */ error RelayerAmountZero(); /** * @dev The collector is zero */ error RelayerCollectorZero(); /** * @dev The recipient is zero */ error RelayerRecipientZero(); /** * @dev The executor is zero */ error RelayerExecutorZero(); /** * @dev Relayer no task given to execute */ error RelayerNoTaskGiven(); /** * @dev Relayer input length mismatch */ error RelayerInputLengthMismatch(); /** * @dev The sender is not allowed */ error RelayerExecutorNotAllowed(address sender); /** * @dev Trying to execute tasks from different smart vaults */ error RelayerMultipleTaskSmartVaults(address task, address taskSmartVault, address expectedSmartVault); /** * @dev The task to execute does not have permissions on the associated smart vault */ error RelayerTaskDoesNotHavePermissions(address task, address smartVault); /** * @dev The smart vault balance plus the available quota are lower than the amount to pay the relayer */ error RelayerPaymentInsufficientBalance(address smartVault, uint256 balance, uint256 quota, uint256 amount); /** * @dev It failed to send amount minus quota to the smart vault's collector */ error RelayerPaymentFailed(address smartVault, uint256 amount, uint256 quota); /** * @dev The smart vault balance is lower than the amount to withdraw */ error RelayerWithdrawInsufficientBalance(address sender, uint256 balance, uint256 amount); /** * @dev It failed to send the amount to the sender */ error RelayerWithdrawFailed(address sender, uint256 amount); /** * @dev The value sent and the amount differ */ error RelayerValueDoesNotMatchAmount(uint256 value, uint256 amount); /** * @dev The simulation executed properly */ error RelayerSimulationResult(TaskResult[] taskResults); /** * @dev Emitted every time an executor is configured */ event ExecutorSet(address indexed executor, bool allowed); /** * @dev Emitted every time the default collector is set */ event DefaultCollectorSet(address indexed collector); /** * @dev Emitted every time a collector is set for a smart vault */ event SmartVaultCollectorSet(address indexed smartVault, address indexed collector); /** * @dev Emitted every time a smart vault's maximum quota is set */ event SmartVaultMaxQuotaSet(address indexed smartVault, uint256 maxQuota); /** * @dev Emitted every time a smart vault's task is executed */ event TaskExecuted( address indexed smartVault, address indexed task, bytes data, bool success, bytes result, uint256 gas, uint256 index ); /** * @dev Emitted every time some native tokens are deposited for the smart vault's balance */ event Deposited(address indexed smartVault, uint256 amount); /** * @dev Emitted every time some native tokens are withdrawn from the smart vault's balance */ event Withdrawn(address indexed smartVault, uint256 amount); /** * @dev Emitted every time some ERC20 tokens are withdrawn from the relayer to an external account */ event FundsRescued(address indexed token, address indexed recipient, uint256 amount); /** * @dev Emitted every time a smart vault's quota is paid */ event QuotaPaid(address indexed smartVault, uint256 amount); /** * @dev Emitted every time a smart vault pays for transaction gas to the relayer */ event GasPaid(address indexed smartVault, uint256 amount, uint256 quota); /** * @dev Task result * @param success Whether the task execution succeeds or not * @param result Result of the task execution */ struct TaskResult { bool success; bytes result; } /** * @dev Tells the default collector address */ function defaultCollector() external view returns (address); /** * @dev Tells whether an executor is allowed * @param executor Address of the executor being queried */ function isExecutorAllowed(address executor) external view returns (bool); /** * @dev Tells the smart vault available balance to relay transactions * @param smartVault Address of the smart vault being queried */ function getSmartVaultBalance(address smartVault) external view returns (uint256); /** * @dev Tells the custom collector address set for a smart vault * @param smartVault Address of the smart vault being queried */ function getSmartVaultCollector(address smartVault) external view returns (address); /** * @dev Tells the smart vault maximum quota to be used * @param smartVault Address of the smart vault being queried */ function getSmartVaultMaxQuota(address smartVault) external view returns (uint256); /** * @dev Tells the smart vault used quota * @param smartVault Address of the smart vault being queried */ function getSmartVaultUsedQuota(address smartVault) external view returns (uint256); /** * @dev Tells the collector address applicable for a smart vault * @param smartVault Address of the smart vault being queried */ function getApplicableCollector(address smartVault) external view returns (address); /** * @dev Configures an external executor * @param executor Address of the executor to be set * @param allowed Whether the given executor should be allowed or not */ function setExecutor(address executor, bool allowed) external; /** * @dev Sets the default collector * @param collector Address of the new default collector to be set */ function setDefaultCollector(address collector) external; /** * @dev Sets a custom collector for a smart vault * @param smartVault Address of smart vault to set a collector for * @param collector Address of the collector to be set for the given smart vault */ function setSmartVaultCollector(address smartVault, address collector) external; /** * @dev Sets a maximum quota for a smart vault * @param smartVault Address of smart vault to set a maximum quota for * @param maxQuota Maximum quota to be set for the given smart vault */ function setSmartVaultMaxQuota(address smartVault, uint256 maxQuota) external; /** * @dev Deposits native tokens for a given smart vault * @param smartVault Address of smart vault to deposit balance for * @param amount Amount of native tokens to be deposited, must match msg.value */ function deposit(address smartVault, uint256 amount) external payable; /** * @dev Withdraws native tokens from a given smart vault * @param amount Amount of native tokens to be withdrawn */ function withdraw(uint256 amount) external; /** * @dev Executes a list of tasks * @param tasks Addresses of the tasks to execute * @param data List of calldata to execute each of the given tasks * @param continueIfFailed Whether the execution should fail in case one of the tasks fail */ function execute(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external; /** * @dev Simulates an execution. * WARNING: THIS METHOD IS MEANT TO BE USED AS A VIEW FUNCTION * This method will always revert. Successful results or task execution errors are returned as * `RelayerSimulationResult` errors. Any other error should be treated as failure. * @param tasks Addresses of the tasks to simulate the execution of * @param data List of calldata to simulate each of the given tasks execution * @param continueIfFailed Whether the simulation should fail in case one of the tasks execution fails */ function simulate(address[] memory tasks, bytes[] memory data, bool continueIfFailed) external; /** * @dev Withdraw ERC20 tokens to an external account. To be used in case of accidental token transfers. * @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 rescueFunds(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/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: MIT // OpenZeppelin Contracts (last updated v4.9.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] * ```solidity * 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. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ 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. * * 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. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * 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. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ 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. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// 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 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 * * 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) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// 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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// 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; 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/axelar/IAxelarConnector.sol'; import './BaseBridgeTask.sol'; import '../interfaces/bridge/IAxelarBridger.sol'; /** * @title Axelar bridger * @dev Task that extends the base bridge task to use Axelar */ contract AxelarBridger is IAxelarBridger, BaseBridgeTask { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('AXELAR_BRIDGER'); /** * @dev Axelar bridge config. Only used in the initializer. */ struct AxelarBridgeConfig { BaseBridgeConfig baseBridgeConfig; } /** * @dev Initializes the Axelar bridger * @param config Axelar bridge config */ function initialize(AxelarBridgeConfig memory config) external virtual initializer { __AxelarBridger_init(config); } /** * @dev Initializes the Axelar bridger. It does call upper contracts initializers. * @param config Axelar bridge config */ function __AxelarBridger_init(AxelarBridgeConfig memory config) internal onlyInitializing { __BaseBridgeTask_init(config.baseBridgeConfig); __AxelarBridger_init_unchained(config); } /** * @dev Initializes the Axelar bridger. It does not call upper contracts initializers. * @param config Axelar bridge config */ function __AxelarBridger_init_unchained(AxelarBridgeConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Axelar bridger */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeAxelarBridger(token, amount); bytes memory connectorData = abi.encodeWithSelector( IAxelarConnector.execute.selector, getDestinationChain(token), token, amount, recipient ); ISmartVault(smartVault).execute(connector, connectorData); _afterAxelarBridger(token, amount); } /** * @dev Before Axelar bridger hook */ function _beforeAxelarBridger(address token, uint256 amount) internal virtual { // Axelar does not support specifying slippage nor fee _beforeBaseBridgeTask(token, amount, 0, 0); } /** * @dev After Axelar bridger task hook */ function _afterAxelarBridger(address token, uint256 amount) internal virtual { // Axelar does not support specifying slippage nor fee _afterBaseBridgeTask(token, amount, 0, 0); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '../Task.sol'; import '../interfaces/bridge/IBaseBridgeTask.sol'; /** * @title Base bridge task * @dev Task that offers the basic components for more detailed bridge tasks */ abstract contract BaseBridgeTask is IBaseBridgeTask, Task { using FixedPoint for uint256; // Connector address address public override connector; // Connector address address public override recipient; // Default destination chain uint256 public override defaultDestinationChain; // Default maximum slippage in fixed point uint256 public override defaultMaxSlippage; // Default maximum fee MaxFee internal _defaultMaxFee; // Destination chain per token address mapping (address => uint256) public override customDestinationChain; // Maximum slippage per token address mapping (address => uint256) public override customMaxSlippage; // Maximum fee per token address mapping (address => MaxFee) internal _customMaxFee; /** * @dev Maximum fee defined by a token address and a max fee value */ struct MaxFee { address token; uint256 amount; } /** * @dev Custom destination chain config. Only used in the initializer. */ struct CustomDestinationChain { address token; uint256 destinationChain; } /** * @dev Custom max slippage config. Only used in the initializer. */ struct CustomMaxSlippage { address token; uint256 maxSlippage; } /** * @dev Custom max fee config. Only used in the initializer. */ struct CustomMaxFee { address token; MaxFee maxFee; } /** * @dev Base bridge config. Only used in the initializer. */ struct BaseBridgeConfig { address connector; address recipient; uint256 destinationChain; uint256 maxSlippage; MaxFee maxFee; CustomDestinationChain[] customDestinationChains; CustomMaxSlippage[] customMaxSlippages; CustomMaxFee[] customMaxFees; TaskConfig taskConfig; } /** * @dev Initializes the base bridge task. It does call upper contracts initializers. * @param config Base bridge config */ function __BaseBridgeTask_init(BaseBridgeConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseBridgeTask_init_unchained(config); } /** * @dev Initializes the base bridge task. It does not call upper contracts initializers. * @param config Base bridge config */ function __BaseBridgeTask_init_unchained(BaseBridgeConfig memory config) internal onlyInitializing { _setConnector(config.connector); _setRecipient(config.recipient); _setDefaultDestinationChain(config.destinationChain); _setDefaultMaxSlippage(config.maxSlippage); MaxFee memory defaultFee = config.maxFee; _setDefaultMaxFee(defaultFee.token, defaultFee.amount); for (uint256 i = 0; i < config.customDestinationChains.length; i++) { CustomDestinationChain memory customConfig = config.customDestinationChains[i]; _setCustomDestinationChain(customConfig.token, customConfig.destinationChain); } for (uint256 i = 0; i < config.customMaxSlippages.length; i++) { _setCustomMaxSlippage(config.customMaxSlippages[i].token, config.customMaxSlippages[i].maxSlippage); } for (uint256 i = 0; i < config.customMaxFees.length; i++) { CustomMaxFee memory customConfig = config.customMaxFees[i]; MaxFee memory maxFee = customConfig.maxFee; _setCustomMaxFee(customConfig.token, maxFee.token, maxFee.amount); } } /** * @dev Tells the default max fee */ function defaultMaxFee() external view override returns (address maxFeeToken, uint256 amount) { MaxFee memory maxFee = _defaultMaxFee; return (maxFee.token, maxFee.amount); } /** * @dev Tells the max fee defined for a specific token * @param token Address of the token being queried */ function customMaxFee(address token) external view override returns (address maxFeeToken, uint256 amount) { MaxFee memory maxFee = _customMaxFee[token]; return (maxFee.token, maxFee.amount); } /** * @dev Tells the destination chain that should be used for a token * @param token Address of the token to get the destination chain for */ function getDestinationChain(address token) public view virtual override returns (uint256) { uint256 chain = customDestinationChain[token]; return chain == 0 ? defaultDestinationChain : chain; } /** * @dev Tells the max slippage that should be used for a token * @param token Address of the token to get the max slippage for */ function getMaxSlippage(address token) public view virtual override returns (uint256) { uint256 maxSlippage = customMaxSlippage[token]; return maxSlippage == 0 ? defaultMaxSlippage : maxSlippage; } /** * @dev Tells the max fee that should be used for a token * @param token Address of the token to get the max fee for */ function getMaxFee(address token) external view virtual override returns (address maxFeeToken, uint256 amount) { MaxFee memory maxFee = _getMaxFee(token); return (maxFee.token, maxFee.amount); } /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Sets the recipient address. Sender must be authorized. * @param newRecipient Address of the new recipient to be set */ function setRecipient(address newRecipient) external override authP(authParams(newRecipient)) { _setRecipient(newRecipient); } /** * @dev Sets the default destination chain * @param destinationChain Default destination chain to be set */ function setDefaultDestinationChain(uint256 destinationChain) external override authP(authParams(destinationChain)) { _setDefaultDestinationChain(destinationChain); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external override authP(authParams(maxSlippage)) { _setDefaultMaxSlippage(maxSlippage); } /** * @dev Sets the default max fee * @param maxFeeToken Default max fee token to be set * @param amount Default max fee amount to be set */ function setDefaultMaxFee(address maxFeeToken, uint256 amount) external override authP(authParams(maxFeeToken, amount)) { _setDefaultMaxFee(maxFeeToken, amount); } /** * @dev Sets a custom destination chain * @param token Address of the token to set a custom destination chain for * @param destinationChain Destination chain to be set */ function setCustomDestinationChain(address token, uint256 destinationChain) external override authP(authParams(token, destinationChain)) { _setCustomDestinationChain(token, destinationChain); } /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external override authP(authParams(token, maxSlippage)) { _setCustomMaxSlippage(token, maxSlippage); } /** * @dev Sets a custom max fee * @param token Address of the token to set a custom max fee for * @param maxFeeToken Max fee token to be set for the given token * @param amount Max fee amount to be set for the given token */ function setCustomMaxFee(address token, address maxFeeToken, uint256 amount) external override authP(authParams(token, maxFeeToken, amount)) { _setCustomMaxFee(token, maxFeeToken, amount); } /** * @dev Tells the max fee that should be used for a token * @param token Address of the token to get the max fee for */ function _getMaxFee(address token) internal view virtual returns (MaxFee memory) { MaxFee memory maxFee = _customMaxFee[token]; return maxFee.token == address(0) ? _defaultMaxFee : maxFee; } /** * @dev Before base bridge task hook */ function _beforeBaseBridgeTask(address token, uint256 amount, uint256 slippage, uint256 fee) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); if (getDestinationChain(token) == 0) revert TaskDestinationChainNotSet(); uint256 maxSlippage = getMaxSlippage(token); if (slippage > maxSlippage) revert TaskSlippageAboveMax(slippage, maxSlippage); // If no fee is given we simply ignore the max fee config if (fee == 0) return; // Otherwise, we revert in case there is no max fee set MaxFee memory maxFee = _getMaxFee(token); if (maxFee.token == address(0)) revert TaskFeeAboveMax(fee, maxFee.amount); uint256 convertedFee = maxFee.token == token ? fee : fee.mulDown(_getPrice(token, maxFee.token)); if (convertedFee > maxFee.amount) revert TaskFeeAboveMax(convertedFee, maxFee.amount); } /** * @dev After base bridge task hook */ function _afterBaseBridgeTask(address token, uint256 amount, uint256, uint256) internal virtual { _afterTask(token, amount); } /** * @dev Sets the balance connectors. Next 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 (next != bytes32(0)) revert TaskNextConnectorNotZero(next); super._setBalanceConnectors(previous, next); } /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } /** * @dev Sets the recipient address * @param newRecipient Address of the new recipient to be set */ function _setRecipient(address newRecipient) internal { if (newRecipient == address(0)) revert TaskRecipientZero(); recipient = newRecipient; emit RecipientSet(newRecipient); } /** * @dev Sets the default destination chain * @param destinationChain Default destination chain to be set */ function _setDefaultDestinationChain(uint256 destinationChain) internal { if (destinationChain == block.chainid) revert TaskBridgeCurrentChainId(destinationChain); defaultDestinationChain = destinationChain; emit DefaultDestinationChainSet(destinationChain); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function _setDefaultMaxSlippage(uint256 maxSlippage) internal { if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); defaultMaxSlippage = maxSlippage; emit DefaultMaxSlippageSet(maxSlippage); } /** * @dev Sets the default max fee * @param maxFeeToken Default max fee token to be set * @param amount Default max fee amount to be set */ function _setDefaultMaxFee(address maxFeeToken, uint256 amount) internal { _setMaxFee(_defaultMaxFee, maxFeeToken, amount); emit DefaultMaxFeeSet(maxFeeToken, amount); } /** * @dev Sets a custom destination chain for a token * @param token Address of the token to set the custom destination chain for * @param destinationChain Destination chain to be set */ function _setCustomDestinationChain(address token, uint256 destinationChain) internal { if (token == address(0)) revert TaskTokenZero(); if (destinationChain == block.chainid) revert TaskBridgeCurrentChainId(destinationChain); customDestinationChain[token] = destinationChain; emit CustomDestinationChainSet(token, destinationChain); } /** * @dev Sets a custom max slippage for a token * @param token Address of the token to set the custom max slippage for * @param maxSlippage Max slippage to be set */ function _setCustomMaxSlippage(address token, uint256 maxSlippage) internal { if (token == address(0)) revert TaskTokenZero(); if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); customMaxSlippage[token] = maxSlippage; emit CustomMaxSlippageSet(token, maxSlippage); } /** * @dev Sets a custom max fee for a token * @param token Address of the token to set the custom max fee for * @param maxFeeToken Max fee token to be set for the given token * @param amount Max fee amount to be set for the given token */ function _setCustomMaxFee(address token, address maxFeeToken, uint256 amount) internal { if (token == address(0)) revert TaskTokenZero(); _setMaxFee(_customMaxFee[token], maxFeeToken, amount); emit CustomMaxFeeSet(token, maxFeeToken, amount); } /** * @dev Sets a max fee * @param maxFee Max fee to be updated * @param token Max fee token to be set * @param amount Max fee amount to be set */ function _setMaxFee(MaxFee storage maxFee, address token, uint256 amount) private { if (token == address(0) && amount != 0) revert TaskInvalidMaxFee(); maxFee.token = token; maxFee.amount = amount; } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/connext/IConnextConnector.sol'; import './BaseBridgeTask.sol'; import '../interfaces/bridge/IConnextBridger.sol'; /** * @title Connext bridger * @dev Task that extends the base bridge task to use Connext */ contract ConnextBridger is IConnextBridger, BaseBridgeTask { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CONNEXT_BRIDGER'); /** * @dev Connext bridge config. Only used in the initializer. */ struct ConnextBridgeConfig { BaseBridgeConfig baseBridgeConfig; } /** * @dev Initializes the Connext bridger * @param config Connext bridge config */ function initialize(ConnextBridgeConfig memory config) external virtual initializer { __ConnextBridger_init(config); } /** * @dev Initializes the Connext bridger. It does call upper contracts initializers. * @param config Connext bridge config */ function __ConnextBridger_init(ConnextBridgeConfig memory config) internal onlyInitializing { __BaseBridgeTask_init(config.baseBridgeConfig); __ConnextBridger_init_unchained(config); } /** * @dev Initializes the Connext bridger. It does not call upper contracts initializers. * @param config Connext bridge config */ function __ConnextBridger_init_unchained(ConnextBridgeConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Connext bridger */ function call(address token, uint256 amount, uint256 slippage, uint256 fee) external override authP(authParams(token, amount, slippage, fee)) { if (amount == 0) amount = getTaskAmount(token); _beforeConnextBridger(token, amount, slippage, fee); uint256 amountAfterFees = amount - fee; uint256 minAmountOut = amountAfterFees.mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IConnextConnector.execute.selector, getDestinationChain(token), token, amount, minAmountOut, recipient, fee ); ISmartVault(smartVault).execute(connector, connectorData); _afterConnextBridger(token, amount, slippage, fee); } /** * @dev Before connext bridger hook */ function _beforeConnextBridger(address token, uint256 amount, uint256 slippage, uint256 fee) internal virtual { _beforeBaseBridgeTask(token, amount, slippage, fee); } /** * @dev After connext bridger hook */ function _afterConnextBridger(address token, uint256 amount, uint256 slippage, uint256 fee) internal virtual { _afterBaseBridgeTask(token, amount, slippage, fee); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/hop/IHopBridgeConnector.sol'; import './BaseBridgeTask.sol'; import '../interfaces/bridge/IHopBridger.sol'; /** * @title Hop bridger * @dev Task that extends the base bridge task to use Hop */ contract HopBridger is IHopBridger, BaseBridgeTask { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('HOP_BRIDGER'); // Relayer address address public override relayer; // Maximum deadline in seconds uint256 public override maxDeadline; // List of Hop entrypoints per token mapping (address => address) public override tokenHopEntrypoint; /** * @dev Token Hop entrypoint config. Only used in the initializer. */ struct TokenHopEntrypoint { address token; address entrypoint; } /** * @dev Hop bridge config. Only used in the initializer. */ struct HopBridgeConfig { address relayer; uint256 maxDeadline; TokenHopEntrypoint[] tokenHopEntrypoints; BaseBridgeConfig baseBridgeConfig; } /** * @dev Initializes the Hop bridger * @param config Hop bridge config */ function initialize(HopBridgeConfig memory config) external virtual initializer { __HopBridger_init(config); } /** * @dev Initializes the Hop bridger. It does call upper contracts initializers. * @param config Hop bridge config */ function __HopBridger_init(HopBridgeConfig memory config) internal onlyInitializing { __BaseBridgeTask_init(config.baseBridgeConfig); __HopBridger_init_unchained(config); } /** * @dev Initializes the Hop bridger. It does not call upper contracts initializers. * @param config Hop bridge config */ function __HopBridger_init_unchained(HopBridgeConfig memory config) internal onlyInitializing { _setRelayer(config.relayer); _setMaxDeadline(config.maxDeadline); for (uint256 i = 0; i < config.tokenHopEntrypoints.length; i++) { TokenHopEntrypoint memory customConfig = config.tokenHopEntrypoints[i]; _setTokenHopEntrypoint(customConfig.token, customConfig.entrypoint); } } /** * @dev Sets the relayer, only used when bridging from L1 to L2 * @param newRelayer New relayer address to be set */ function setRelayer(address newRelayer) external override authP(authParams(newRelayer)) { _setRelayer(newRelayer); } /** * @dev Sets the max deadline * @param newMaxDeadline New max deadline to be set */ function setMaxDeadline(uint256 newMaxDeadline) external override authP(authParams(newMaxDeadline)) { _setMaxDeadline(newMaxDeadline); } /** * @dev Sets an entrypoint for a tokens * @param token Token address to set a Hop entrypoint for * @param entrypoint Hop entrypoint address to be set for a token */ function setTokenHopEntrypoint(address token, address entrypoint) external override authP(authParams(token, entrypoint)) { _setTokenHopEntrypoint(token, entrypoint); } /** * @dev Execute Hop bridger */ function call(address token, uint256 amount, uint256 slippage, uint256 fee) external override authP(authParams(token, amount, slippage, fee)) { if (amount == 0) amount = getTaskAmount(token); _beforeHopBridger(token, amount, slippage, fee); uint256 amountAfterFees = amount - fee; uint256 minAmountOut = amountAfterFees.mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IHopBridgeConnector.execute.selector, getDestinationChain(token), token, amount, minAmountOut, recipient, tokenHopEntrypoint[token], block.timestamp + maxDeadline, relayer, fee ); ISmartVault(smartVault).execute(connector, connectorData); _afterHopBridger(token, amount, slippage, fee); } /** * @dev Before Hop bridger hook */ function _beforeHopBridger(address token, uint256 amount, uint256 slippage, uint256 fee) internal virtual { _beforeBaseBridgeTask(token, amount, slippage, fee); if (tokenHopEntrypoint[token] == address(0)) revert TaskMissingHopEntrypoint(); } /** * @dev After Hop bridger hook */ function _afterHopBridger(address token, uint256 amount, uint256 slippage, uint256 fee) internal virtual { _afterBaseBridgeTask(token, amount, slippage, fee); } /** * @dev Sets the relayer address, only used when bridging from L1 to L2 */ function _setRelayer(address _relayer) internal { relayer = _relayer; emit RelayerSet(_relayer); } /** * @dev Sets the max deadline */ function _setMaxDeadline(uint256 _maxDeadline) internal { if (_maxDeadline == 0) revert TaskMaxDeadlineZero(); maxDeadline = _maxDeadline; emit MaxDeadlineSet(_maxDeadline); } /** * @dev Set a Hop entrypoint for a token * @param token Address of the token to set a Hop entrypoint for * @param entrypoint Hop entrypoint to be set */ function _setTokenHopEntrypoint(address token, address entrypoint) internal { if (token == address(0)) revert TaskTokenZero(); tokenHopEntrypoint[token] = entrypoint; emit TokenHopEntrypointSet(token, entrypoint); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/wormhole/IWormholeConnector.sol'; import './BaseBridgeTask.sol'; import '../interfaces/bridge/IWormholeBridger.sol'; /** * @title Wormhole bridger * @dev Task that extends the bridger task to use Wormhole */ contract WormholeBridger is IWormholeBridger, BaseBridgeTask { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('WORMHOLE_BRIDGER'); /** * @dev Wormhole bridge config. Only used in the initializer. */ struct WormholeBridgeConfig { BaseBridgeConfig baseBridgeConfig; } /** * @dev Initializes the Wormhole bridger * @param config Wormhole bridge config */ function initialize(WormholeBridgeConfig memory config) external virtual initializer { __WormholeBridger_init(config); } /** * @dev Initializes the Wormhole bridger. It does call upper contracts initializers. * @param config Wormhole bridge config */ function __WormholeBridger_init(WormholeBridgeConfig memory config) internal onlyInitializing { __BaseBridgeTask_init(config.baseBridgeConfig); __WormholeBridger_init_unchained(config); } /** * @dev Initializes the Wormhole bridger. It does not call upper contracts initializers. * @param config Wormhole bridge config */ function __WormholeBridger_init_unchained(WormholeBridgeConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Wormhole bridger */ function call(address token, uint256 amount, uint256 fee) external override authP(authParams(token, amount, fee)) { if (amount == 0) amount = getTaskAmount(token); _beforeWormholeBridger(token, amount, fee); uint256 minAmountOut = amount - fee; bytes memory connectorData = abi.encodeWithSelector( IWormholeConnector.execute.selector, getDestinationChain(token), token, amount, minAmountOut, recipient ); ISmartVault(smartVault).execute(connector, connectorData); _afterWormholeBridger(token, amount, fee); } /** * @dev Before Wormhole bridger hook */ function _beforeWormholeBridger(address token, uint256 amount, uint256 fee) internal virtual { // Wormhole does not support specifying slippage _beforeBaseBridgeTask(token, amount, 0, fee); } /** * @dev After Wormhole bridger hook */ function _afterWormholeBridger(address token, uint256 amount, uint256 fee) internal virtual { // Wormhole does not support specifying slippage _afterBaseBridgeTask(token, amount, 0, fee); } }
// 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 be 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 './IBaseBridgeTask.sol'; /** * @dev Axelar bridger task interface */ interface IAxelarBridger is IBaseBridgeTask { /** * @dev Execute Axelar bridger task */ function call(address token, uint256 amountIn) 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 '../ITask.sol'; /** * @dev Base bridge task interface */ interface IBaseBridgeTask is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The recipient is zero */ error TaskRecipientZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev The next balance connector is not zero */ error TaskNextConnectorNotZero(bytes32 id); /** * @dev The destination chain is not set */ error TaskDestinationChainNotSet(); /** * @dev The destination chain id is the same as the current chain id */ error TaskBridgeCurrentChainId(uint256 destinationChain); /** * @dev The slippage to be set is greater than one */ error TaskSlippageAboveOne(); /** * @dev The requested slippage is greater than the maximum slippage */ error TaskSlippageAboveMax(uint256 slippage, uint256 maxSlippage); /** * @dev The requested fee is greater than the maximum fee */ error TaskFeeAboveMax(uint256 fee, uint256 maxFee); /** * @dev The max fee token is zero but the max fee value is not zero */ error TaskInvalidMaxFee(); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Emitted every time the recipient is set */ event RecipientSet(address indexed recipient); /** * @dev Emitted every time the default destination chain is set */ event DefaultDestinationChainSet(uint256 indexed defaultDestinationChain); /** * @dev Emitted every time the default max slippage is set */ event DefaultMaxSlippageSet(uint256 maxSlippage); /** * @dev Emitted every time the default max fee is set */ event DefaultMaxFeeSet(address indexed maxFeeToken, uint256 amount); /** * @dev Emitted every time a custom destination chain is set for a token */ event CustomDestinationChainSet(address indexed token, uint256 indexed destinationChain); /** * @dev Emitted every time a custom max slippage is set */ event CustomMaxSlippageSet(address indexed token, uint256 maxSlippage); /** * @dev Emitted every time a custom max fee is set */ event CustomMaxFeeSet(address indexed token, address indexed maxFeeToken, uint256 amount); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Tells the address of the allowed recipient */ function recipient() external view returns (address); /** * @dev Tells the default destination chain */ function defaultDestinationChain() external view returns (uint256); /** * @dev Tells the default max slippage */ function defaultMaxSlippage() external view returns (uint256); /** * @dev Tells the default max fee */ function defaultMaxFee() external view returns (address maxFeeToken, uint256 amount); /** * @dev Tells the destination chain defined for a specific token * @param token Address of the token being queried */ function customDestinationChain(address token) external view returns (uint256); /** * @dev Tells the max slippage defined for a specific token * @param token Address of the token being queried */ function customMaxSlippage(address token) external view returns (uint256); /** * @dev Tells the max fee defined for a specific token * @param token Address of the token being queried */ function customMaxFee(address token) external view returns (address maxFeeToken, uint256 amount); /** * @dev Tells the destination chain that should be used for a token * @param token Address of the token to get the destination chain for */ function getDestinationChain(address token) external view returns (uint256); /** * @dev Tells the max slippage that should be used for a token * @param token Address of the token to get the max slippage for */ function getMaxSlippage(address token) external view returns (uint256); /** * @dev Tells the max fee that should be used for a token * @param token Address of the token to get the max fee for */ function getMaxFee(address token) external view returns (address maxFeeToken, uint256 amount); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external; /** * @dev Sets the recipient address * @param recipient Address of the new recipient to be set */ function setRecipient(address recipient) external; /** * @dev Sets the default destination chain * @param destinationChain Default destination chain to be set */ function setDefaultDestinationChain(uint256 destinationChain) external; /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external; /** * @dev Sets the default max fee * @param maxFeeToken Default max fee token to be set * @param amount Default max fee amount to be set */ function setDefaultMaxFee(address maxFeeToken, uint256 amount) external; /** * @dev Sets a custom destination chain for a token * @param token Address of the token to set a custom destination chain for * @param destinationChain Destination chain to be set */ function setCustomDestinationChain(address token, uint256 destinationChain) external; /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external; /** * @dev Sets a custom max fee * @param token Address of the token to set a custom max fee for * @param maxFeeToken Max fee token to be set for the given token * @param amount Max fee amount to be set for the given token */ function setCustomMaxFee(address token, address maxFeeToken, 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 './IBaseBridgeTask.sol'; /** * @dev Connext bridger task interface */ interface IConnextBridger is IBaseBridgeTask { /** * @dev Execute Connext bridger task */ function call(address token, uint256 amountIn, uint256 slippage, uint256 relayerFee) 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 './IBaseBridgeTask.sol'; /** * @dev Hop bridger task interface */ interface IHopBridger is IBaseBridgeTask { /** * @dev The max deadline is zero */ error TaskMaxDeadlineZero(); /** * @dev The Hop entrypoint is zero */ error TaskMissingHopEntrypoint(); /** * @dev Emitted every time the relayer is set */ event RelayerSet(address indexed relayer); /** * @dev Emitted every time the max deadline is set */ event MaxDeadlineSet(uint256 maxDeadline); /** * @dev Emitted every time a Hop entrypoint is set for a token */ event TokenHopEntrypointSet(address indexed token, address indexed entrypoint); /** * @dev Tells the relayer address, only used when bridging from L1 to L2 */ function relayer() external view returns (address); /** * @dev Tells the max deadline */ function maxDeadline() external view returns (uint256); /** * @dev Tells Hop entrypoint set for a token */ function tokenHopEntrypoint(address token) external view returns (address entrypoint); /** * @dev Sets the relayer, only used when bridging from L1 to L2 * @param relayer New relayer address to be set */ function setRelayer(address relayer) external; /** * @dev Sets the max deadline * @param maxDeadline New max deadline to be set */ function setMaxDeadline(uint256 maxDeadline) external; /** * @dev Sets an entrypoint for a tokens * @param token Token address to set a Hop entrypoint for * @param entrypoint Hop entrypoint address to be set for a token */ function setTokenHopEntrypoint(address token, address entrypoint) external; /** * @dev Execution function */ function call(address token, uint256 amountIn, uint256 slippage, uint256 fee) 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 './IBaseBridgeTask.sol'; /** * @dev Wormhole bridger task interface */ interface IWormholeBridger is IBaseBridgeTask { /** * @dev Execute Wormhole bridger task */ function call(address token, uint256 amountIn, uint256 fee) 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 './IBalancerPool.sol'; interface IBalancerBoostedPool is IBalancerPool { function getRate() external view returns (uint256); function getBptIndex() external view returns (uint256); }
// 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 './IBalancerPool.sol'; interface IBalancerLinearPool is IBalancerPool { function getRate() external view returns (uint256); function getMainToken() 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; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; interface IBalancerPool is IERC20 { function getPoolId() external view returns (bytes32); }
// 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 '../../ITask.sol'; /** * @dev Balancer V2 pool exit task interface */ interface IBalancerV2PoolExiter is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev The slippage to be set is greater than one */ error TaskSlippageAboveOne(); /** * @dev The requested slippage is greater than the maximum slippage */ error TaskSlippageAboveMax(uint256 slippage, uint256 maxSlippage); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Emitted every time the default max slippage is set */ event DefaultMaxSlippageSet(uint256 maxSlippage); /** * @dev Emitted every time a custom max slippage is set */ event CustomMaxSlippageSet(address indexed token, uint256 maxSlippage); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Tells the default token threshold */ function defaultMaxSlippage() external view returns (uint256); /** * @dev Tells the max slippage defined for a specific token * @param token Address of the token being queried */ function customMaxSlippage(address token) external view returns (uint256); /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) external view returns (uint256); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external; /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external; /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external; /** * @dev Execute Balancer v2 pool exiter * @param tokenIn Address of the Balancer pool token to exit * @param amountIn Amount of Balancer pool tokens to exit * @param slippage Slippage to be applied */ function call(address tokenIn, uint256 amountIn, uint256 slippage) 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 '@openzeppelin/contracts/token/ERC20/IERC20.sol'; interface IBalancerVault { function getPool(bytes32 poolId) external view returns (address, uint256); function getPoolTokens(bytes32 poolId) external view returns (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock); struct JoinPoolRequest { IERC20[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } function joinPool(bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request) external payable; struct ExitPoolRequest { IERC20[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function exitPool(bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request) external; enum SwapKind { GIVEN_IN, GIVEN_OUT } struct SingleSwap { bytes32 poolId; SwapKind kind; address assetIn; address assetOut; uint256 amount; bytes userData; } struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline) external payable returns (uint256); struct BatchSwapStep { bytes32 poolId; uint256 assetInIndex; uint256 assetOutIndex; uint256 amount; bytes userData; } function batchSwap( SwapKind kind, BatchSwapStep[] memory swaps, address[] memory assets, FundManagement memory funds, int256[] memory limits, uint256 deadline ) external payable returns (int256[] memory); }
// 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 '../../ITask.sol'; /** * @dev Base Convex task interface */ interface IBaseConvexTask is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) 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 './IBaseConvexTask.sol'; /** * @dev Convex claimer task interface */ interface IConvexClaimer is IBaseConvexTask { /** * @dev The amount is not zero */ error TaskAmountNotZero(); /** * @dev The previous balance connector is not zero */ error TaskPreviousConnectorNotZero(bytes32 id); /** * @dev The length of the claim result mismatch */ error TaskClaimResultLengthMismatch(); /** * @dev Executes the Convex 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 './IBaseConvexTask.sol'; /** * @dev Convex exiter task interface */ interface IConvexExiter is IBaseConvexTask { /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev Executes the Convex exiter 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 './IBaseConvexTask.sol'; /** * @dev Convex joiner task interface */ interface IConvexJoiner is IBaseConvexTask { /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev Executes the Convex joiner 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 '../../ITask.sol'; /** * @dev Base Curve task interface */ interface IBaseCurveTask is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev The token out is not set */ error TaskTokenOutNotSet(); /** * @dev The slippage to be set is greater than one */ error TaskSlippageAboveOne(); /** * @dev The requested slippage is greater than the maximum slippage */ error TaskSlippageAboveMax(uint256 slippage, uint256 maxSlippage); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Emitted every time the default token out is set */ event DefaultTokenOutSet(address indexed tokenOut); /** * @dev Emitted every time the default max slippage is set */ event DefaultMaxSlippageSet(uint256 maxSlippage); /** * @dev Emitted every time a custom token out is set */ event CustomTokenOutSet(address indexed token, address tokenOut); /** * @dev Emitted every time a custom max slippage is set */ event CustomMaxSlippageSet(address indexed token, uint256 maxSlippage); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Tells the default token out */ function defaultTokenOut() external view returns (address); /** * @dev Tells the default token threshold */ function defaultMaxSlippage() external view returns (uint256); /** * @dev Tells the token out defined for a specific token * @param token Address of the token being queried */ function customTokenOut(address token) external view returns (address); /** * @dev Tells the max slippage defined for a specific token * @param token Address of the token being queried */ function customMaxSlippage(address token) external view returns (uint256); /** * @dev Tells the token out that should be used for a token */ function getTokenOut(address token) external view returns (address); /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) external view returns (uint256); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external; /** * @dev Sets the default token out * @param tokenOut Address of the default token out to be set */ function setDefaultTokenOut(address tokenOut) external; /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external; /** * @dev Sets a custom token out * @param token Address of the token to set a custom token out for * @param tokenOut Address of the token out to be set */ function setCustomTokenOut(address token, address tokenOut) external; /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) 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 './IBaseCurveTask.sol'; /** * @dev Curve 2CRV exiter task interface */ interface ICurve2CrvExiter is IBaseCurveTask { /** * @dev Executes the Curve 2CRV exiter task */ function call(address token, uint256 amount, uint256 slippage) 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 './IBaseCurveTask.sol'; /** * @dev Curve 2CRV joiner task interface */ interface ICurve2CrvJoiner is IBaseCurveTask { /** * @dev Executes the Curve 2CRV joiner task */ function call(address token, uint256 amount, uint256 slippage) 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 '../../ITask.sol'; /** * @dev Base ERC4626 task interface */ interface IBaseERC4626Task is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) 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 './IBaseERC4626Task.sol'; /** * @dev ERC4626 exiter task interface */ interface IERC4626Exiter is IBaseERC4626Task { /** * @dev Executes the ERC4626 exiter task */ function call(address erc4626, uint256 amount, uint256 minAmountOut) 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 './IBaseERC4626Task.sol'; /** * @dev ERC4626 joiner task interface */ interface IERC4626Joiner is IBaseERC4626Task { /** * The ERC4626 reference is zero */ error TaskERC4626Zero(); /** * @dev Executes the ERC4626 joiner task */ function call(address token, uint256 amount, address erc4626, uint256 minAmountOut) 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 '../ITask.sol'; /** * @dev Collector task interface */ interface ICollector is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The tokens source is zero */ error TaskTokensSourceZero(); /** * @dev The previous balance connector is not zero */ error TaskPreviousConnectorNotZero(bytes32 id); /** * @dev Emitted every time the tokens source is set */ event TokensSourceSet(address indexed tokensSource); /** * @dev Sets the tokens source address * @param tokensSource Address of the tokens source to be set */ function setTokensSource(address tokensSource) external; /** * @dev Executes the collector 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 '../ITask.sol'; /** * @dev Depositor task interface */ interface IDepositor is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The msg value is zero */ error TaskValueZero(); /** * @dev The previous balance connector is not zero */ error TaskPreviousConnectorNotZero(bytes32 id); /** * @dev Executes the withdrawer 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 '../ITask.sol'; /** * @dev Hand over task interface */ interface IHandleOver is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The tokens source is zero */ error TaskConnectorZero(bytes32 id); /** * @dev Executes the hand over 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 '../ITask.sol'; /** * @dev Unwrapper task interface */ interface IUnwrapper is ITask { /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The token is not the wrapped native token */ error TaskTokenNotWrapped(); /** * @dev Executes the unwrapper 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 '../ITask.sol'; /** * @dev Withdrawer task interface */ interface IWithdrawer is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The recipient is zero */ error TaskRecipientZero(); /** * @dev The recipient to be set is the smart vault */ error TaskRecipientEqualsSmartVault(address recipient); /** * @dev The next balance connector is not zero */ error TaskNextConnectorNotZero(bytes32 id); /** * @dev Emitted every time the recipient is set */ event RecipientSet(address indexed recipient); /** * @dev Tells the address of the allowed recipient */ function recipient() external view returns (address); /** * @dev Sets the recipient address * @param recipient Address of the new recipient to be set */ function setRecipient(address recipient) external; /** * @dev Executes the withdrawer 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 '../ITask.sol'; /** * @dev Wrapper task interface */ interface IWrapper is ITask { /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The token is not the native token */ error TaskTokenNotNative(); /** * @dev Executes the wrapper 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 '../ITask.sol'; /** * @dev Base relayer fund task interface */ interface IBaseRelayerFundTask is ITask { /** * @dev The relayer is zero */ error TaskRelayerZero(); /** * @dev The task initializer is disabled */ error TaskInitializerDisabled(); /** * @dev There is no threshold set for the given token */ error TaskTokenThresholdNotSet(address token); /** * @dev The deposited amount is above the minimum threshold */ error TaskDepositAboveMinThreshold(uint256 balance, uint256 min); /** * @dev The new amount to be deposited does not cover the used quota */ error TaskDepositBelowUsedQuota(uint256 amount, uint256 quota); /** * @dev The requested amount would result in a new balance below the minimum threshold */ error TaskNewDepositBelowMinThreshold(uint256 balance, uint256 min); /** * @dev The requested amount would result in a new balance above the maximum threshold */ error TaskNewDepositAboveMaxThreshold(uint256 balance, uint256 max); /** * @dev Emitted every time the relayer is set */ event RelayerSet(address indexed relayer); /** * @dev Tells the relayer */ function relayer() external view returns (address); /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function setRelayer(address newRelayer) 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 '../ITask.sol'; /** * @dev Relayer depositor task interface */ interface IRelayerDepositor is ITask { /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The relayer is zero */ error TaskRelayerZero(); /** * @dev Emitted every time the relayer is set */ event RelayerSet(address indexed relayer); /** * @dev Tells the relayer */ function relayer() external view returns (address); /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function setRelayer(address newRelayer) external; /** * @dev Executes the relayer depositor 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 './IBaseSwapTask.sol'; /** * @dev Balancer v2 BPT swapper task interface */ interface IBalancerV2BptSwapper is IBaseSwapTask { /** * @dev Execution function */ function call(address tokenIn, uint256 amountIn, uint256 slippage) 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 '../ITask.sol'; /** * @dev Base swap task interface */ interface IBaseSwapTask is ITask { /** * @dev The token is zero */ error TaskTokenZero(); /** * @dev The amount is zero */ error TaskAmountZero(); /** * @dev The connector is zero */ error TaskConnectorZero(); /** * @dev The token out is not set */ error TaskTokenOutNotSet(); /** * @dev The slippage to be set is greater than one */ error TaskSlippageAboveOne(); /** * @dev The slippage is greater than the maximum slippage */ error TaskSlippageAboveMax(uint256 slippage, uint256 maxSlippage); /** * @dev Emitted every time the connector is set */ event ConnectorSet(address indexed connector); /** * @dev Emitted every time the default token out is set */ event DefaultTokenOutSet(address indexed tokenOut); /** * @dev Emitted every time the default max slippage is set */ event DefaultMaxSlippageSet(uint256 maxSlippage); /** * @dev Emitted every time a custom token out is set */ event CustomTokenOutSet(address indexed token, address tokenOut); /** * @dev Emitted every time a custom max slippage is set */ event CustomMaxSlippageSet(address indexed token, uint256 maxSlippage); /** * @dev Tells the connector tied to the task */ function connector() external view returns (address); /** * @dev Tells the default token out */ function defaultTokenOut() external view returns (address); /** * @dev Tells the default max slippage */ function defaultMaxSlippage() external view returns (uint256); /** * @dev Tells the token out defined for a specific token * @param token Address of the token being queried */ function customTokenOut(address token) external view returns (address); /** * @dev Tells the max slippage defined for a specific token * @param token Address of the token being queried */ function customMaxSlippage(address token) external view returns (uint256); /** * @dev Tells the token out that should be used for a token */ function getTokenOut(address token) external view returns (address); /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) external view returns (uint256); /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external; /** * @dev Sets the default token out * @param tokenOut Address of the default token out to be set */ function setDefaultTokenOut(address tokenOut) external; /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external; /** * @dev Sets a custom token out * @param token Address of the token to set a custom token out for * @param tokenOut Address of the token out to be set */ function setCustomTokenOut(address token, address tokenOut) external; /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) 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 './IBaseSwapTask.sol'; /** * @dev L2 Hop swapper task interface */ interface IHopL2Swapper is IBaseSwapTask { /** * @dev The amm for the token is not set */ error TaskMissingHopTokenAmm(); /** * @dev The hToken to be set is not the hToken of the Hop L2 amm to be used */ error TaskHopTokenAmmMismatch(address hToken, address amm); /** * @dev Emitted every time an AMM is set for a token */ event TokenAmmSet(address indexed token, address amm); /** * @dev Tells AMM set for a token */ function tokenAmm(address token) external view returns (address); /** * @dev Sets an AMM for a hToken * @param hToken Address of the hToken to be set * @param amm AMM address to be set for the hToken */ function setTokenAmm(address hToken, address amm) external; /** * @dev Executes the L2 hop swapper task */ function call(address tokenIn, uint256 amountIn, uint256 slippage) 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 './IBaseSwapTask.sol'; /** * @dev 1inch v5 swapper task interface */ interface IOneInchV5Swapper is IBaseSwapTask { /** * @dev Execution function */ function call(address tokenIn, uint256 amountIn, uint256 slippage, bytes memory data) 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 './IBaseSwapTask.sol'; /** * @dev Paraswap v5 swapper task interface */ interface IParaswapV5Swapper is IBaseSwapTask { /** * @dev The quote signer is zero */ error TaskQuoteSignerZero(); /** * @dev The signer to be set is not the quote signer */ error TaskInvalidQuoteSigner(address signer, address quoteSigner); /** * @dev The deadline is in the past */ error TaskQuoteSignerPastDeadline(uint256 deadline, uint256 currentTimestamp); /** * @dev Emitted every time a quote signer is set */ event QuoteSignerSet(address indexed quoteSigner); /** * @dev Tells the address of the allowed quote signer */ function quoteSigner() external view returns (address); /** * @dev Sets the quote signer address. Sender must be authorized. * @param newQuoteSigner Address of the new quote signer to be set */ function setQuoteSigner(address newQuoteSigner) external; /** * @dev Executes Paraswap V5 swapper task */ function call( address tokenIn, uint256 amountIn, uint256 minAmountOut, uint256 expectedAmountOut, uint256 deadline, bytes memory data, bytes memory sig ) 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 './IBaseSwapTask.sol'; /** * @dev Uniswap v2 swapper task interface */ interface IUniswapV2Swapper is IBaseSwapTask { /** * @dev Execution function */ function call(address tokenIn, uint256 amountIn, uint256 slippage, address[] memory hopTokens) 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 './IBaseSwapTask.sol'; /** * @dev Uniswap v3 swapper task interface */ interface IUniswapV3Swapper is IBaseSwapTask { /** * @dev Execution function */ function call( address tokenIn, uint256 amountIn, uint256 slippage, uint24 fee, address[] memory hopTokens, uint24[] memory hopFees ) 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 '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2Vault.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2PoolConnector.sol'; import '../../Task.sol'; import '../../interfaces/liquidity/balancer/IBalancerPool.sol'; import '../../interfaces/liquidity/balancer/IBalancerV2PoolExiter.sol'; /** * @title Balancer v2 pool exiter * @dev Task that offers the components to exit Balancer pools */ contract BalancerV2PoolExiter is IBalancerV2PoolExiter, Task { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('BALANCER_V2_POOL_EXITER'); // Task connector address address public override connector; // Default maximum slippage in fixed point uint256 public override defaultMaxSlippage; // Maximum slippage per token address mapping (address => uint256) public override customMaxSlippage; /** * @dev Custom max slippage config. Only used in the initializer. */ struct CustomMaxSlippage { address token; uint256 maxSlippage; } /** * @dev Balancer pool exit config. Only used in the initializer. */ struct BalancerPoolExitConfig { address connector; uint256 maxSlippage; CustomMaxSlippage[] customMaxSlippages; TaskConfig taskConfig; } /** * @dev Initializes a Balancer v2 pool exiter * @param config Balancer pool exit config */ function initialize(BalancerPoolExitConfig memory config) external virtual initializer { __BalancerV2PoolExiter_init(config); } /** * @dev Initializes the Balancer v2 pool exiter. It does call upper contracts initializers. * @param config Balancer pool exit config */ function __BalancerV2PoolExiter_init(BalancerPoolExitConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BalancerV2PoolExiter_init_unchained(config); } /** * @dev Initializes the Balancer v2 pool exiter. It does not call upper contracts initializers. * @param config Balancer pool exit config */ function __BalancerV2PoolExiter_init_unchained(BalancerPoolExitConfig memory config) internal onlyInitializing { _setConnector(config.connector); _setDefaultMaxSlippage(config.maxSlippage); for (uint256 i = 0; i < config.customMaxSlippages.length; i++) { _setCustomMaxSlippage(config.customMaxSlippages[i].token, config.customMaxSlippages[i].maxSlippage); } } /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) public view virtual override returns (uint256) { uint256 maxSlippage = customMaxSlippage[token]; return maxSlippage == 0 ? defaultMaxSlippage : maxSlippage; } /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external override authP(authParams(maxSlippage)) { _setDefaultMaxSlippage(maxSlippage); } /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external override authP(authParams(token, maxSlippage)) { _setCustomMaxSlippage(token, maxSlippage); } /** * @dev Execute Balancer v2 pool exiter * @param tokenIn Address of the Balancer pool token to exit * @param amountIn Amount of Balancer pool tokens to exit * @param slippage Slippage to be applied */ function call(address tokenIn, uint256 amountIn, uint256 slippage) external override authP(authParams(tokenIn, amountIn, slippage)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); _beforeBalancerV2PoolExiter(tokenIn, amountIn, slippage); (address[] memory tokensOut, uint256[] memory minAmountsOut) = _getTokensOut(tokenIn, amountIn, slippage); bytes memory connectorData = abi.encodeWithSelector( IBalancerV2PoolConnector.exit.selector, tokenIn, amountIn, tokensOut, minAmountsOut ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); uint256[] memory amountsOut = abi.decode(result, (uint256[])); _afterBalancerV2PoolExiter(tokenIn, amountIn, tokensOut, amountsOut); } /** * @dev Tells the list of tokens and min amounts out based on a number of BPTs to exit * @param tokenIn Address of the pool being exited * @param amountIn Amount of tokens to exit the pool with * @param slippage Slippage to be used */ function _getTokensOut(address tokenIn, uint256 amountIn, uint256 slippage) internal view returns (address[] memory tokensOut, uint256[] memory minAmountsOut) { uint256 bptTotalSupply = IERC20(tokenIn).totalSupply(); uint256 bptRatio = amountIn.divDown(bptTotalSupply); bytes32 poolId = IBalancerPool(tokenIn).getPoolId(); address balancerV2Vault = IBalancerV2PoolConnector(connector).balancerV2Vault(); (IERC20[] memory tokens, uint256[] memory balances, ) = IBalancerV2Vault(balancerV2Vault).getPoolTokens(poolId); tokensOut = new address[](tokens.length); minAmountsOut = new uint256[](tokens.length); for (uint256 i = 0; i < tokens.length; i++) { tokensOut[i] = address(tokens[i]); uint256 expectedAmountsOut = balances[i].mulDown(bptRatio); minAmountsOut[i] = expectedAmountsOut.mulDown(FixedPoint.ONE - slippage); } } /** * @dev Before Balancer v2 pool exiter hook */ function _beforeBalancerV2PoolExiter(address tokenIn, uint256 amountIn, uint256 slippage) internal virtual { _beforeTask(tokenIn, amountIn); if (tokenIn == address(0)) revert TaskTokenZero(); if (amountIn == 0) revert TaskAmountZero(); uint256 maxSlippage = getMaxSlippage(tokenIn); if (slippage > maxSlippage) revert TaskSlippageAboveMax(slippage, maxSlippage); } /** * @dev After Balancer v2 pool exiter hook */ function _afterBalancerV2PoolExiter( address tokenIn, uint256 amountIn, address[] memory tokensOut, uint256[] memory amountsOut ) internal virtual { for (uint256 i = 0; i < tokensOut.length; i++) _increaseBalanceConnector(tokensOut[i], amountsOut[i]); _afterTask(tokenIn, amountIn); } /** * @dev Sets the task connector * @param newConnector New connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function _setDefaultMaxSlippage(uint256 maxSlippage) internal { if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); defaultMaxSlippage = maxSlippage; emit DefaultMaxSlippageSet(maxSlippage); } /** * @dev Sets a custom max slippage for a token * @param token Address of the token to set the custom max slippage for * @param maxSlippage Max slippage to be set */ function _setCustomMaxSlippage(address token, uint256 maxSlippage) internal { if (token == address(0)) revert TaskTokenZero(); if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); customMaxSlippage[token] = maxSlippage; emit CustomMaxSlippageSet(token, maxSlippage); } }
// 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 '../../Task.sol'; import '../../interfaces/liquidity/convex/IBaseConvexTask.sol'; /** * @title Base Convex task * @dev Task that offers the basic components for more detailed Convex related tasks */ abstract contract BaseConvexTask is IBaseConvexTask, Task { // Task connector address address public override connector; /** * @dev Base Convex config. Only used in the initializer. */ struct BaseConvexConfig { address connector; TaskConfig taskConfig; } /** * @dev Initializes the base Convex task. It does call upper contracts initializers. * @param config Base Convex config */ function __BaseConvexTask_init(BaseConvexConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseConvexTask_init_unchained(config); } /** * @dev Initializes the base Convex task. It does not call upper contracts initializers. * @param config Base Convex config */ function __BaseConvexTask_init_unchained(BaseConvexConfig memory config) internal onlyInitializing { _setConnector(config.connector); } /** * @dev Sets the task connector * @param newConnector Address of the new connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Before base Convex task hook */ function _beforeBaseConvexTask(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); } /** * @dev After base Convex task hook */ function _afterBaseConvexTask(address token, uint256 amount) internal virtual { _afterTask(token, amount); } /** * @dev Sets the task connector * @param newConnector New connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } }
// 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-connectors/contracts/interfaces/convex/IConvexConnector.sol'; import './BaseConvexTask.sol'; import '../../interfaces/liquidity/convex/IConvexClaimer.sol'; /** * @title Convex claimer */ contract ConvexClaimer is IConvexClaimer, BaseConvexTask { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CONVEX_CLAIMER'); /** * @dev Convex claim config. Only used in the initializer. */ struct ConvexClaimConfig { BaseConvexConfig baseConvexConfig; } /** * @dev Initializes a Convex claimer * @param config Convex claim config */ function initialize(ConvexClaimConfig memory config) external virtual initializer { __ConvexClaimer_init(config); } /** * @dev Initializes the Convex claimer. It does call upper contracts initializers. * @param config Convex claim config */ function __ConvexClaimer_init(ConvexClaimConfig memory config) internal onlyInitializing { __BaseConvexTask_init(config.baseConvexConfig); __ConvexClaimer_init_unchained(config); } /** * @dev Initializes the Convex claimer. It does not call upper contracts initializers. * @param config Convex claim config */ function __ConvexClaimer_init_unchained(ConvexClaimConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @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 IConvexConnector(connector).booster(); } /** * @dev Tells the amount a task should use for a token, in this case always zero since it is not possible to * compute on-chain how many tokens are available to be claimed. */ function getTaskAmount(address) public pure virtual override(IBaseTask, BaseTask) returns (uint256) { return 0; } /** * @dev Execute Convex claimer * @param token Address of the Convex pool token to claim rewards for * @param amount Must be zero, it is not possible to claim a specific number of tokens */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeConvexClaimer(token, amount); bytes memory connectorData = abi.encodeWithSelector(IConvexConnector.claim.selector, token); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); (address[] memory tokens, uint256[] memory amounts) = abi.decode(result, (address[], uint256[])); _afterConvexClaimer(token, amount, tokens, amounts); } /** * @dev Before Convex claimer hook */ function _beforeConvexClaimer(address token, uint256 amount) internal virtual { _beforeBaseConvexTask(token, amount); if (amount != 0) revert TaskAmountNotZero(); } /** * @dev After Convex claimer hook */ function _afterConvexClaimer( address tokenIn, uint256 amountIn, address[] memory tokensOut, uint256[] memory amountsOut ) internal virtual { if (tokensOut.length != amountsOut.length) revert TaskClaimResultLengthMismatch(); for (uint256 i = 0; i < tokensOut.length; i++) _increaseBalanceConnector(tokensOut[i], amountsOut[i]); _afterBaseConvexTask(tokenIn, amountIn); } /** * @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-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/convex/IConvexConnector.sol'; import './BaseConvexTask.sol'; import '../../interfaces/liquidity/convex/IConvexExiter.sol'; /** * @title Convex exiter * @dev Task that extends the base Convex task to exit Convex pools */ contract ConvexExiter is IConvexExiter, BaseConvexTask { using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CONVEX_EXITER'); /** * @dev Convex exit config. Only used in the initializer. */ struct ConvexExitConfig { BaseConvexConfig baseConvexConfig; } /** * @dev Initializes a Convex exiter * @param config Convex exit config */ function initialize(ConvexExitConfig memory config) external virtual initializer { __ConvexExiter_init(config); } /** * @dev Initializes the Convex exiter. It does call upper contracts initializers. * @param config Convex exit config */ function __ConvexExiter_init(ConvexExitConfig memory config) internal onlyInitializing { __BaseConvexTask_init(config.baseConvexConfig); __ConvexExiter_init_unchained(config); } /** * @dev Initializes the Convex exiter. It does not call upper contracts initializers. * @param config Convex exit config */ function __ConvexExiter_init_unchained(ConvexExitConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the Convex exiter task * @param token Address of the Convex pool token to be exited with * @param amount Amount of Convex pool tokens to be exited with */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeConvexExiter(token, amount); bytes memory connectorData = abi.encodeWithSelector(IConvexConnector.exit.selector, token, amount); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterConvexExiter(token, amount, IConvexConnector(connector).getCurvePool(token), result.toUint256()); } /** * @dev Before Convex exiter hook */ function _beforeConvexExiter(address token, uint256 amount) internal virtual { _beforeBaseConvexTask(token, amount); if (amount == 0) revert TaskAmountZero(); } /** * @dev After Convex exiter hook */ function _afterConvexExiter(address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) internal virtual { _increaseBalanceConnector(tokenOut, amountOut); _afterBaseConvexTask(tokenIn, amountIn); } }
// 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-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/convex/IConvexConnector.sol'; import './BaseConvexTask.sol'; import '../../interfaces/liquidity/convex/IConvexJoiner.sol'; /** * @title Convex joiner * @dev Task that extends the base Convex task to join Convex pools */ contract ConvexJoiner is IConvexJoiner, BaseConvexTask { using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CONVEX_JOINER'); /** * @dev Convex join config. Only used in the initializer. */ struct ConvexJoinConfig { BaseConvexConfig baseConvexConfig; } /** * @dev Initializes a Convex joiner * @param config Convex join config */ function initialize(ConvexJoinConfig memory config) external virtual initializer { __ConvexJoiner_init(config); } /** * @dev Initializes the Convex joiner. It does call upper contracts initializers. * @param config Convex join config */ function __ConvexJoiner_init(ConvexJoinConfig memory config) internal onlyInitializing { __BaseConvexTask_init(config.baseConvexConfig); __ConvexJoiner_init_unchained(config); } /** * @dev Initializes the Convex joiner. It does not call upper contracts initializers. * @param config Convex join config */ function __ConvexJoiner_init_unchained(ConvexJoinConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the Convex joiner task * @param token Address of the Curve pool token to be joined with * @param amount Amount of Curve pool tokens to be joined with */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeConvexJoiner(token, amount); bytes memory connectorData = abi.encodeWithSelector(IConvexConnector.join.selector, token, amount); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterConvexJoiner(token, amount, IConvexConnector(connector).getCvxPool(token), result.toUint256()); } /** * @dev Before Convex joiner hook */ function _beforeConvexJoiner(address token, uint256 amount) internal virtual { _beforeBaseConvexTask(token, amount); if (amount == 0) revert TaskAmountZero(); } /** * @dev After Convex joiner hook */ function _afterConvexJoiner(address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) internal virtual { _increaseBalanceConnector(tokenOut, amountOut); _afterBaseConvexTask(tokenIn, amountIn); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '../../Task.sol'; import '../../interfaces/liquidity/curve/IBaseCurveTask.sol'; /** * @title Base Curve task * @dev Task that offers the basic components for more detailed Curve related tasks */ abstract contract BaseCurveTask is IBaseCurveTask, Task { using FixedPoint for uint256; // Task connector address address public override connector; // Default token out address public override defaultTokenOut; // Default maximum slippage in fixed point uint256 public override defaultMaxSlippage; // Token out per token mapping (address => address) public override customTokenOut; // Maximum slippage per token address mapping (address => uint256) public override customMaxSlippage; /** * @dev Custom token out config. Only used in the initializer. */ struct CustomTokenOut { address token; address tokenOut; } /** * @dev Custom max slippage config. Only used in the initializer. */ struct CustomMaxSlippage { address token; uint256 maxSlippage; } /** * @dev Base Curve config. Only used in the initializer. */ struct BaseCurveConfig { address connector; address tokenOut; uint256 maxSlippage; CustomTokenOut[] customTokensOut; CustomMaxSlippage[] customMaxSlippages; TaskConfig taskConfig; } /** * @dev Initializes the base Curve task. It does call upper contracts initializers. * @param config Base Curve config */ function __BaseCurveTask_init(BaseCurveConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseCurveTask_init_unchained(config); } /** * @dev Initializes the base Curve task. It does not call upper contracts initializers. * @param config Base Curve config */ function __BaseCurveTask_init_unchained(BaseCurveConfig memory config) internal onlyInitializing { _setConnector(config.connector); _setDefaultTokenOut(config.tokenOut); _setDefaultMaxSlippage(config.maxSlippage); for (uint256 i = 0; i < config.customTokensOut.length; i++) { _setCustomTokenOut(config.customTokensOut[i].token, config.customTokensOut[i].tokenOut); } for (uint256 i = 0; i < config.customMaxSlippages.length; i++) { _setCustomMaxSlippage(config.customMaxSlippages[i].token, config.customMaxSlippages[i].maxSlippage); } } /** * @dev Tells the token out that should be used for a token */ function getTokenOut(address token) public view virtual override returns (address) { address tokenOut = customTokenOut[token]; return tokenOut == address(0) ? defaultTokenOut : tokenOut; } /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) public view virtual override returns (uint256) { uint256 maxSlippage = customMaxSlippage[token]; return maxSlippage == 0 ? defaultMaxSlippage : maxSlippage; } /** * @dev Sets the task connector * @param newConnector Address of the new connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Sets the default token out * @param tokenOut Address of the default token out to be set */ function setDefaultTokenOut(address tokenOut) external override authP(authParams(tokenOut)) { _setDefaultTokenOut(tokenOut); } /** * @dev Sets the default max slippage */ function setDefaultMaxSlippage(uint256 maxSlippage) external override authP(authParams(maxSlippage)) { _setDefaultMaxSlippage(maxSlippage); } /** * @dev Sets a custom token out * @param token Address of the token to set a custom token out for * @param tokenOut Address of the token out to be set */ function setCustomTokenOut(address token, address tokenOut) external override authP(authParams(token, tokenOut)) { _setCustomTokenOut(token, tokenOut); } /** * @dev Sets a a custom max slippage * @param token Address of the token to set a max slippage for * @param maxSlippage Max slippage to be set for the given token */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external override authP(authParams(token, maxSlippage)) { _setCustomMaxSlippage(token, maxSlippage); } /** * @dev Before base Curve task hook */ function _beforeBaseCurveTask(address token, uint256 amount, uint256 slippage) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); if (getTokenOut(token) == address(0)) revert TaskTokenOutNotSet(); uint256 maxSlippage = getMaxSlippage(token); if (slippage > maxSlippage) revert TaskSlippageAboveMax(slippage, maxSlippage); } /** * @dev After base Curve task hook */ function _afterBaseCurveTask(address tokenIn, uint256 amountIn, uint256, address tokenOut, uint256 amountOut) internal virtual { _increaseBalanceConnector(tokenOut, amountOut); _afterTask(tokenIn, amountIn); } /** * @dev Sets the task connector * @param newConnector New connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } /** * @dev Sets the default token out * @param tokenOut Default token out to be set */ function _setDefaultTokenOut(address tokenOut) internal { defaultTokenOut = tokenOut; emit DefaultTokenOutSet(tokenOut); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function _setDefaultMaxSlippage(uint256 maxSlippage) internal { if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); defaultMaxSlippage = maxSlippage; emit DefaultMaxSlippageSet(maxSlippage); } /** * @dev Sets a custom token out for a token * @param token Address of the token to set the custom token out for * @param tokenOut Address of the token out to be set */ function _setCustomTokenOut(address token, address tokenOut) internal { if (token == address(0)) revert TaskTokenZero(); customTokenOut[token] = tokenOut; emit CustomTokenOutSet(token, tokenOut); } /** * @dev Sets a custom max slippage for a token * @param token Address of the token to set the custom max slippage for * @param maxSlippage Max slippage to be set */ function _setCustomMaxSlippage(address token, uint256 maxSlippage) internal { if (token == address(0)) revert TaskTokenZero(); if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); customMaxSlippage[token] = maxSlippage; emit CustomMaxSlippageSet(token, maxSlippage); } }
// 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-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/curve/ICurve2CrvConnector.sol'; import './BaseCurveTask.sol'; import '../../interfaces/liquidity/curve/ICurve2CrvExiter.sol'; /** * @title Curve 2CRV exiter * @dev Task that extends the base Curve task to exit 2CRV pools */ contract Curve2CrvExiter is ICurve2CrvExiter, BaseCurveTask { using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CURVE_2CRV_EXITER'); /** * @dev Curve 2CRV exit config. Only used in the initializer. */ struct Curve2CrvExitConfig { BaseCurveConfig baseCurveConfig; } /** * @dev Initializes a Curve 2CRV exiter * @param config Curve 2CRV exit config */ function initialize(Curve2CrvExitConfig memory config) external virtual initializer { __Curve2CrvExiter_init(config); } /** * @dev Initializes the Curve 2CRV exiter. It does call upper contracts initializers. * @param config Curve 2CRV exit config */ function __Curve2CrvExiter_init(Curve2CrvExitConfig memory config) internal onlyInitializing { __BaseCurveTask_init(config.baseCurveConfig); __Curve2CrvExiter_init_unchained(config); } /** * @dev Initializes the Curve 2CRV exiter. It does not call upper contracts initializers. * @param config Curve 2CRV exit config */ function __Curve2CrvExiter_init_unchained(Curve2CrvExitConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Curve 2CRV exiter * @param token Address of the Curve pool token to exit * @param amount Amount of Curve pool tokens to exit */ function call(address token, uint256 amount, uint256 slippage) external override authP(authParams(token, amount, slippage)) { if (amount == 0) amount = getTaskAmount(token); _beforeCurve2CrvExiter(token, amount, slippage); address tokenOut = getTokenOut(token); bytes memory connectorData = abi.encodeWithSelector( ICurve2CrvConnector.exit.selector, token, amount, tokenOut, slippage ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterCurve2CrvExiter(token, amount, slippage, tokenOut, result.toUint256()); } /** * @dev Before Curve 2CRV exiter hook */ function _beforeCurve2CrvExiter(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseCurveTask(token, amount, slippage); } /** * @dev After Curve 2CRV exiter hook */ function _afterCurve2CrvExiter( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseCurveTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/curve/ICurve2CrvConnector.sol'; import './BaseCurveTask.sol'; import '../../interfaces/liquidity/curve/ICurve2CrvJoiner.sol'; /** * @title Curve 2CRV joiner * @dev Task that extends the base Curve task to join 2CRV pools */ contract Curve2CrvJoiner is ICurve2CrvJoiner, BaseCurveTask { using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('CURVE_2CRV_JOINER'); /** * @dev Curve 2CRV join config. Only used in the initializer. */ struct Curve2CrvJoinConfig { BaseCurveConfig baseCurveConfig; } /** * @dev Initializes a Curve 2CRV joiner * @param config Curve 2CRV join config */ function initialize(Curve2CrvJoinConfig memory config) external virtual initializer { __Curve2CrvJoiner_init(config); } /** * @dev Initializes the Curve 2CRV joiner. It does call upper contracts initializers. * @param config Curve 2CRV join config */ function __Curve2CrvJoiner_init(Curve2CrvJoinConfig memory config) internal onlyInitializing { __BaseCurveTask_init(config.baseCurveConfig); __Curve2CrvJoiner_init_unchained(config); } /** * @dev Initializes the Curve 2CRV joiner. It does not call upper contracts initializers. * @param config Curve 2CRV join config */ function __Curve2CrvJoiner_init_unchained(Curve2CrvJoinConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Curve 2CRV joiner * @param token Address of the token to join the Curve pool with * @param amount Amount of tokens to join the Curve pool with */ function call(address token, uint256 amount, uint256 slippage) external override authP(authParams(token, amount, slippage)) { if (amount == 0) amount = getTaskAmount(token); _beforeCurve2CrvJoiner(token, amount, slippage); address tokenOut = getTokenOut(token); bytes memory connectorData = abi.encodeWithSelector( ICurve2CrvConnector.join.selector, tokenOut, token, amount, slippage ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterCurve2CrvJoiner(token, amount, slippage, tokenOut, result.toUint256()); } /** * @dev Before Curve 2CRV joiner hook */ function _beforeCurve2CrvJoiner(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseCurveTask(token, amount, slippage); } /** * @dev After Curve 2CRV joiner hook */ function _afterCurve2CrvJoiner( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseCurveTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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 '../../Task.sol'; import '../../interfaces/liquidity/erc4626/IBaseERC4626Task.sol'; /** * @title Base ERC4626 task * @dev Task that offers the basic components for more detailed ERC4626 related tasks */ abstract contract BaseERC4626Task is IBaseERC4626Task, Task { // Task connector address address public override connector; /** * @dev Base ERC4626 config. Only used in the initializer. */ struct BaseERC4626Config { address connector; TaskConfig taskConfig; } /** * @dev Initializes the base ERC4626 task. It does call upper contracts initializers. * @param config Base ERC4626 config */ function __BaseERC4626Task_init(BaseERC4626Config memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseERC4626Task_init_unchained(config); } /** * @dev Initializes the base ERC4626 task. It does not call upper contracts initializers. * @param config Base ERC4626 config */ function __BaseERC4626Task_init_unchained(BaseERC4626Config memory config) internal onlyInitializing { _setConnector(config.connector); } /** * @dev Sets the task connector * @param newConnector Address of the new connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Before base ERC4626 task hook */ function _beforeBaseERC4626Task(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After base ERC4626 task hook */ function _afterBaseERC4626Task(address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) internal virtual { _increaseBalanceConnector(tokenOut, amountOut); _afterTask(tokenIn, amountIn); } /** * @dev Sets the task connector * @param newConnector New connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } }
// 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-connectors/contracts/interfaces/erc4626/IERC4626Connector.sol'; import './BaseERC4626Task.sol'; import '../../interfaces/liquidity/erc4626/IERC4626Exiter.sol'; /** * @title ERC4626 exiter * @dev Task that extends the base ERC4626 task to exit an ERC4626 vault */ contract ERC4626Exiter is IERC4626Exiter, BaseERC4626Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('ERC4626_EXITER'); /** * @dev ERC4626 exit config. Only used in the initializer. */ struct ERC4626ExitConfig { BaseERC4626Config baseERC4626Config; } /** * @dev Initializes a ERC4626 exiter * @param config ERC4626 exit config */ function initialize(ERC4626ExitConfig memory config) external virtual initializer { __ERC4626Exiter_init(config); } /** * @dev Initializes the ERC4626 exiter. It does call upper contracts initializers. * @param config ERC4626 exit config */ function __ERC4626Exiter_init(ERC4626ExitConfig memory config) internal onlyInitializing { __BaseERC4626Task_init(config.baseERC4626Config); __ERC4626Exiter_init_unchained(config); } /** * @dev Initializes the ERC4626 exiter. It does not call upper contracts initializers. * @param config ERC4626 exit config */ function __ERC4626Exiter_init_unchained(ERC4626ExitConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the ERC4626 exiter task. Note that the ERC4626 is also the token. * @param erc4626 Address of the ERC4626 to be exited * @param amount Amount of shares to be exited with * @param minAmountOut Minimum amount of assets willing to receive */ function call(address erc4626, uint256 amount, uint256 minAmountOut) external override authP(authParams(erc4626, amount, minAmountOut)) { if (amount == 0) amount = getTaskAmount(erc4626); _beforeERC4626Exiter(erc4626, amount); bytes memory connectorData = abi.encodeWithSelector( IERC4626Connector.exit.selector, erc4626, amount, minAmountOut ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); (address tokenOut, uint256 amountOut) = abi.decode(result, (address, uint256)); _afterERC4626Exiter(erc4626, amount, tokenOut, amountOut); } /** * @dev Before ERC4626 exiter hook */ function _beforeERC4626Exiter(address token, uint256 amount) internal virtual { _beforeBaseERC4626Task(token, amount); } /** * @dev After ERC4626 exiter hook */ function _afterERC4626Exiter(address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) internal virtual { _afterBaseERC4626Task(tokenIn, amountIn, tokenOut, amountOut); } }
// 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-connectors/contracts/interfaces/erc4626/IERC4626Connector.sol'; import './BaseERC4626Task.sol'; import '../../interfaces/liquidity/erc4626/IERC4626Joiner.sol'; /** * @title ERC4626 joiner * @dev Task that extends the base ERC4626 task to join an ERC4626 vault */ contract ERC4626Joiner is IERC4626Joiner, BaseERC4626Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('ERC4626_JOINER'); /** * @dev ERC4626 join config. Only used in the initializer. */ struct ERC4626JoinConfig { BaseERC4626Config baseERC4626Config; } /** * @dev Initializes a ERC4626 joiner * @param config ERC4626 join config */ function initialize(ERC4626JoinConfig memory config) external virtual initializer { __ERC4626Joiner_init(config); } /** * @dev Initializes the ERC4626 joiner. It does call upper contracts initializers. * @param config ERC4626 join config */ function __ERC4626Joiner_init(ERC4626JoinConfig memory config) internal onlyInitializing { __BaseERC4626Task_init(config.baseERC4626Config); __ERC4626Joiner_init_unchained(config); } /** * @dev Initializes the ERC4626 joiner. It does not call upper contracts initializers. * @param config ERC4626 join config */ function __ERC4626Joiner_init_unchained(ERC4626JoinConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the ERC4626 joiner task * @param token Address of the token to be joined with * @param amount Amount of assets to be joined with * @param erc4626 Address of the ERC4626 to be joined * @param minAmountOut Minimum amount of shares willing to receive */ function call(address token, uint256 amount, address erc4626, uint256 minAmountOut) external override authP(authParams(token, amount, erc4626, minAmountOut)) { if (amount == 0) amount = getTaskAmount(token); _beforeERC4626Joiner(token, amount, erc4626); bytes memory connectorData = abi.encodeWithSelector( IERC4626Connector.join.selector, erc4626, token, amount, minAmountOut ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); (address tokenOut, uint256 amountOut) = abi.decode(result, (address, uint256)); _afterERC4626Joiner(token, amount, tokenOut, amountOut); } /** * @dev Before ERC4626 joiner hook */ function _beforeERC4626Joiner(address token, uint256 amount, address erc4626) internal virtual { _beforeBaseERC4626Task(token, amount); if (erc4626 == address(0)) revert TaskERC4626Zero(); } /** * @dev After ERC4626 joiner hook */ function _afterERC4626Joiner(address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) internal virtual { _afterBaseERC4626Task(tokenIn, amountIn, tokenOut, amountOut); } }
// 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-helpers/contracts/utils/ERC20Helpers.sol'; import '../Task.sol'; import '../interfaces/primitives/ICollector.sol'; /** * @title Collector * @dev Task that offers a source address where funds can be pulled from */ contract Collector is ICollector, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('COLLECTOR'); // Address from where the tokens will be pulled address internal _tokensSource; /** * @dev Collect config. Only used in the initializer. */ struct CollectConfig { address tokensSource; TaskConfig taskConfig; } /** * @dev Initializes the collector * @param config Collect config */ function initialize(CollectConfig memory config) external virtual initializer { __Collector_init(config); } /** * @dev Initializes the collector. It does call upper contracts initializers. * @param config Collect config */ function __Collector_init(CollectConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __Collector_init_unchained(config); } /** * @dev Initializes the collector. It does not call upper contracts initializers. * @param config Collect config */ function __Collector_init_unchained(CollectConfig memory config) internal onlyInitializing { _setTokensSource(config.tokensSource); } /** * @dev Tells the address from where the token amounts to execute this task are fetched */ function getTokensSource() public view virtual override(IBaseTask, BaseTask) returns (address) { return _tokensSource; } /** * @dev Tells the balance of the depositor for a given token * @param token Address of the token being queried */ function getTaskAmount(address token) public view virtual override(IBaseTask, BaseTask) returns (uint256) { return ERC20Helpers.balanceOf(token, getTokensSource()); } /** * @dev Sets the tokens source address. Sender must be authorized. * @param tokensSource Address of the tokens source to be set */ function setTokensSource(address tokensSource) external override authP(authParams(tokensSource)) { _setTokensSource(tokensSource); } /** * @dev Execute Collector */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeCollector(token, amount); ISmartVault(smartVault).collect(token, _tokensSource, amount); _afterCollector(token, amount); } /** * @dev Before collector hook */ function _beforeCollector(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After collector hook */ function _afterCollector(address token, uint256 amount) internal virtual { _increaseBalanceConnector(token, amount); _afterTask(token, amount); } /** * @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); } /** * @dev Sets the source address * @param tokensSource Address of the tokens source to be set */ function _setTokensSource(address tokensSource) internal virtual { if (tokensSource == address(0)) revert TaskTokensSourceZero(); _tokensSource = tokensSource; emit TokensSourceSet(tokensSource); } }
// 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-helpers/contracts/utils/ERC20Helpers.sol'; import '../Task.sol'; import '../interfaces/primitives/IHandleOver.sol'; /** * @title Hand over task * @dev Task that simply moves tokens from one balance connector to the other */ contract HandleOver is IHandleOver, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('HANDLE_OVER'); /** * @dev Hand over config. Only used in the initializer. */ struct HandleOverConfig { TaskConfig taskConfig; } /** * @dev Initializes the hand over task * @param config Hand over config */ function initialize(HandleOverConfig memory config) external virtual initializer { __HandleOver_init(config); } /** * @dev Initializes the hand over task. It does call upper contracts initializers. * @param config Hand over config */ function __HandleOver_init(HandleOverConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __HandleOver_init_unchained(config); } /** * @dev Initializes the hand over task. It does not call upper contracts initializers. * @param config Hand over config */ function __HandleOver_init_unchained(HandleOverConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute the hand over taks */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeHandleOver(token, amount); _afterHandleOver(token, amount); } /** * @dev Before hand over task hook */ function _beforeHandleOver(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After hand over task hook */ function _afterHandleOver(address token, uint256 amount) internal virtual { _increaseBalanceConnector(token, amount); _afterTask(token, amount); } /** * @dev Sets the balance connectors. Both balance connector must be set. * @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 TaskConnectorZero(previous); if (next == bytes32(0)) revert TaskConnectorZero(next); 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 '../Task.sol'; import '../interfaces/primitives/IUnwrapper.sol'; /** * @title Unwrapper * @dev Task that offers facilities to unwrap wrapped native tokens */ contract Unwrapper is IUnwrapper, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('UNWRAPPER'); /** * @dev Unwrap config. Only used in the initializer. * @param taskConfig Task config params */ struct UnwrapConfig { TaskConfig taskConfig; } /** * @dev Initializes the unwrapper * @param config Unwrap config */ function initialize(UnwrapConfig memory config) external virtual initializer { __Unwrapper_init(config); } /** * @dev Initializes the unwrapper. It does call upper contracts initializers. * @param config Unwrap config */ function __Unwrapper_init(UnwrapConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __Unwrapper_init_unchained(config); } /** * @dev Initializes the unwrapper. It does not call upper contracts initializers. * @param config Unwrap config */ function __Unwrapper_init_unchained(UnwrapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Unwrapper */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeUnwrapper(token, amount); ISmartVault(smartVault).unwrap(amount); _afterUnwrapper(token, amount); } /** * @dev Before unwrapper hook */ function _beforeUnwrapper(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token != _wrappedNativeToken()) revert TaskTokenNotWrapped(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After unwrapper hook */ function _afterUnwrapper(address token, uint256 amount) internal virtual { _increaseBalanceConnector(Denominations.NATIVE_TOKEN, amount); _afterTask(token, amount); } }
// 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 '../Task.sol'; import '../interfaces/primitives/IWithdrawer.sol'; /** * @title Withdrawer * @dev Task that offers a recipient address where funds can be withdrawn */ contract Withdrawer is IWithdrawer, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('WITHDRAWER'); // Address where tokens will be transferred to address public override recipient; /** * @dev Withdraw config. Only used in the initializer. */ struct WithdrawConfig { address recipient; TaskConfig taskConfig; } /** * @dev Initializes the withdrawer * @param config Withdraw config */ function initialize(WithdrawConfig memory config) external virtual initializer { __Withdrawer_init(config); } /** * @dev Initializes the withdrawer. It does call upper contracts initializers. * @param config Withdraw config */ function __Withdrawer_init(WithdrawConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __Withdrawer_init_unchained(config); } /** * @dev Initializes the withdrawer. It does not call upper contracts initializers. * @param config Withdraw config */ function __Withdrawer_init_unchained(WithdrawConfig memory config) internal onlyInitializing { _setRecipient(config.recipient); } /** * @dev Sets the recipient address. Sender must be authorized. * @param newRecipient Address of the new recipient to be set */ function setRecipient(address newRecipient) external override authP(authParams(newRecipient)) { _setRecipient(newRecipient); } /** * @dev Executes the Withdrawer */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeWithdrawer(token, amount); ISmartVault(smartVault).withdraw(token, recipient, amount); _afterWithdrawer(token, amount); } /** * @dev Before withdrawer hook */ function _beforeWithdrawer(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After withdrawer hook */ function _afterWithdrawer(address token, uint256 amount) internal virtual { _afterTask(token, amount); } /** * @dev Sets the recipient address * @param newRecipient Address of the new recipient to be set */ function _setRecipient(address newRecipient) internal { if (newRecipient == address(0)) revert TaskRecipientZero(); if (newRecipient == smartVault) revert TaskRecipientEqualsSmartVault(newRecipient); recipient = newRecipient; emit RecipientSet(newRecipient); } /** * @dev Sets the balance connectors. Next 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 (next != bytes32(0)) revert TaskNextConnectorNotZero(next); 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-helpers/contracts/utils/Denominations.sol'; import '../Task.sol'; import '../interfaces/primitives/IWrapper.sol'; /** * @title Wrapper * @dev Task that offers facilities to wrap native tokens */ contract Wrapper is IWrapper, Task { // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('WRAPPER'); /** * @dev Wrap config. Only used in the initializer. */ struct WrapConfig { TaskConfig taskConfig; } /** * @dev Initializes the wrapper * @param config Wrap config */ function initialize(WrapConfig memory config) external virtual initializer { __Wrapper_init(config); } /** * @dev Initializes the wrapper. It does call upper contracts initializers. * @param config Wrap config */ function __Wrapper_init(WrapConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __Wrapper_init_unchained(config); } /** * @dev Initializes the wrapper. It does not call upper contracts initializers. * @param config Wrap config */ function __Wrapper_init_unchained(WrapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Execute Wrapper */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeWrapper(token, amount); ISmartVault(smartVault).wrap(amount); _afterWrapper(token, amount); } /** * @dev Before wrapper hook */ function _beforeWrapper(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (token != Denominations.NATIVE_TOKEN) revert TaskTokenNotNative(); if (amount == 0) revert TaskAmountZero(); } /** * @dev After wrapper hook */ function _afterWrapper(address token, uint256 amount) internal virtual { _increaseBalanceConnector(_wrappedNativeToken(), amount); _afterTask(token, amount); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-relayer/contracts/interfaces/IRelayer.sol'; import '../Task.sol'; import '../interfaces/relayer/IBaseRelayerFundTask.sol'; /** * @title Base relayer fund task * @dev Task that offers the basic components for more detailed relayer fund tasks */ abstract contract BaseRelayerFundTask is IBaseRelayerFundTask, Task { using FixedPoint for uint256; // Reference to the contract to be funded address public override relayer; /** * @dev Base relayer fund config. Only used in the initializer. */ struct BaseRelayerFundConfig { address relayer; TaskConfig taskConfig; } /** * @dev Initializes the base relayer fund task. It does call upper contracts initializers. * @param config Base relayer fund config */ function __BaseRelayerFundTask_init(BaseRelayerFundConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseRelayerFundTask_init_unchained(config); } /** * @dev Initializes the base relayer fund task. It does not call upper contracts initializers. * @param config Base relayer fund config */ function __BaseRelayerFundTask_init_unchained(BaseRelayerFundConfig memory config) internal onlyInitializing { _setRelayer(config.relayer); } /** * @dev Tells the amount in `token` to be paid to the relayer * @param token Address of the token to be used to pay the relayer */ function getTaskAmount(address token) public view virtual override(IBaseTask, BaseTask) returns (uint256) { Threshold memory threshold = _getTokenThreshold(token); if (threshold.token == address(0)) return 0; uint256 depositedThresholdToken = _getDepositedInThresholdToken(threshold.token); if (depositedThresholdToken >= threshold.min) return 0; uint256 usedQuotaThresholdToken = _getUsedQuotaInThresholdToken(threshold.token); uint256 diff = threshold.max - depositedThresholdToken + usedQuotaThresholdToken; return (token == threshold.token) ? diff : diff.mulUp(_getPrice(threshold.token, token)); } /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function setRelayer(address newRelayer) external override authP(authParams(newRelayer)) { _setRelayer(newRelayer); } /** * @dev Before token threshold task hook */ function _beforeTokenThresholdTask(address token, uint256 amount) internal virtual override { Threshold memory threshold = _getTokenThreshold(token); if (threshold.token == address(0)) revert TaskTokenThresholdNotSet(token); uint256 amountInThresholdToken = amount.mulUp(_getPrice(token, threshold.token)); uint256 depositedInThresholdToken = _getDepositedInThresholdToken(threshold.token); bool isCurrentBalanceAboveMin = depositedInThresholdToken >= threshold.min; if (isCurrentBalanceAboveMin) revert TaskDepositAboveMinThreshold(depositedInThresholdToken, threshold.min); uint256 usedQuotaInThresholdToken = _getUsedQuotaInThresholdToken(threshold.token); bool coversUsedQuota = amountInThresholdToken > usedQuotaInThresholdToken; if (!coversUsedQuota) revert TaskDepositBelowUsedQuota(amountInThresholdToken, usedQuotaInThresholdToken); uint256 balanceAfterDeposit = amountInThresholdToken + depositedInThresholdToken - usedQuotaInThresholdToken; bool isNewBalanceBelowMin = balanceAfterDeposit < threshold.min; if (isNewBalanceBelowMin) revert TaskNewDepositBelowMinThreshold(balanceAfterDeposit, threshold.min); bool isNewBalanceAboveMax = balanceAfterDeposit > threshold.max; if (isNewBalanceAboveMax) revert TaskNewDepositAboveMaxThreshold(balanceAfterDeposit, threshold.max); } /** * @dev Tells the deposited balance in the relayer expressed in another token */ function _getDepositedInThresholdToken(address token) internal view returns (uint256) { // Relayer balance is expressed in ETH uint256 depositedNativeToken = IRelayer(relayer).getSmartVaultBalance(smartVault); return depositedNativeToken.mulUp(_getPrice(_wrappedNativeToken(), token)); } /** * @dev Tells the used quota in the relayer expressed in another token */ function _getUsedQuotaInThresholdToken(address token) internal view returns (uint256) { // Relayer used quota is expressed in ETH uint256 usedQuotaNativeToken = IRelayer(relayer).getSmartVaultUsedQuota(smartVault); return usedQuotaNativeToken.mulUp(_getPrice(_wrappedNativeToken(), token)); } /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function _setRelayer(address newRelayer) internal { if (newRelayer == address(0)) revert TaskRelayerZero(); relayer = newRelayer; emit RelayerSet(newRelayer); } }
// 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 '../primitives/Collector.sol'; import './BaseRelayerFundTask.sol'; /** * @title Collector relayer funder * @dev Task used to convert funds in order to pay relayers using an collector */ contract CollectorRelayerFunder is BaseRelayerFundTask, Collector { /** * @dev Disables the default collector initializer */ function initialize(CollectConfig memory) external pure override { revert TaskInitializerDisabled(); } /** * @dev Initializes the collector relayer funder * @param config Collect config * @param relayer Relayer address */ function initializeCollectorRelayerFunder(CollectConfig memory config, address relayer) external virtual initializer { __CollectorRelayerFunder_init(config, relayer); } /** * @dev Initializes the collector relayer funder. It does call upper contracts initializers. * @param config Collect config * @param relayer Relayer address */ function __CollectorRelayerFunder_init(CollectConfig memory config, address relayer) internal onlyInitializing { __Collector_init(config); __BaseRelayerFundTask_init_unchained(BaseRelayerFundConfig(relayer, config.taskConfig)); __CollectorRelayerFunder_init_unchained(config, relayer); } /** * @dev Initializes the collector relayer funder. It does not call upper contracts initializers. * @param config Collect config * @param relayer Relayer address */ function __CollectorRelayerFunder_init_unchained(CollectConfig memory config, address relayer) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Tells the address from where the token amounts to execute this task are fetched */ function getTokensSource() public view override(Collector, IBaseTask, BaseTask) returns (address) { return Collector.getTokensSource(); } /** * @dev Tells the `token` amount to be funded * @param token Address of the token to be used to fund the relayer */ function getTaskAmount(address token) public view override(BaseRelayerFundTask, Collector) returns (uint256) { return BaseRelayerFundTask.getTaskAmount(token); } /** * @dev Before token threshold task hook */ function _beforeTokenThresholdTask(address token, uint256 amount) internal override(BaseRelayerFundTask, TokenThresholdTask) { BaseRelayerFundTask._beforeTokenThresholdTask(token, amount); } /** * @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(Collector, BaseTask) { Collector._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 './BaseRelayerFundTask.sol'; import '../swap/OneInchV5Swapper.sol'; /** * @title 1inch v5 relayer funder * @dev Task used to convert funds in order to pay relayers using a 1inch v5 swapper */ contract OneInchV5RelayerFunder is BaseRelayerFundTask, OneInchV5Swapper { /** * @dev Disables the default 1inch v5 swapper initializer */ function initialize(OneInchV5SwapConfig memory) external pure override { revert TaskInitializerDisabled(); } /** * @dev Initializes the 1inch v5 relayer funder * @param config 1inch v5 swap config * @param relayer Relayer address */ function initializeOneInchV5RelayerFunder(OneInchV5SwapConfig memory config, address relayer) external virtual initializer { __OneInchV5RelayerFunder_init(config, relayer); } /** * @dev Initializes the 1inch v5 relayer funder. It does call upper contracts initializers. * @param config 1inch v5 swap config * @param relayer Relayer address */ function __OneInchV5RelayerFunder_init(OneInchV5SwapConfig memory config, address relayer) internal onlyInitializing { __OneInchV5Swapper_init(config); __BaseRelayerFundTask_init_unchained(BaseRelayerFundConfig(relayer, config.baseSwapConfig.taskConfig)); __OneInchV5RelayerFunder_init_unchained(config, relayer); } /** * @dev Initializes the 1inch v5 relayer funder. It does not call upper contracts initializers. * @param config Unwrap config * @param relayer Relayer address */ function __OneInchV5RelayerFunder_init_unchained(OneInchV5SwapConfig memory config, address relayer) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Tells the amount in `token` to be funded * @param token Address of the token to be used for funding */ function getTaskAmount(address token) public view override(BaseRelayerFundTask, IBaseTask, BaseTask) returns (uint256) { return BaseRelayerFundTask.getTaskAmount(token); } /** * @dev Before token threshold task hook */ function _beforeTokenThresholdTask(address token, uint256 amount) internal override(BaseRelayerFundTask, TokenThresholdTask) { BaseRelayerFundTask._beforeTokenThresholdTask(token, amount); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-relayer/contracts/interfaces/IRelayer.sol'; import '../Task.sol'; import '../interfaces/relayer/IRelayerDepositor.sol'; /** * @title Relayer depositor * @dev Task that offers facilities to deposit balance for Mimic relayers */ contract RelayerDepositor is IRelayerDepositor, Task { using FixedPoint for uint256; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('RELAYER_DEPOSITOR'); // Reference to the contract to be funded address public override relayer; /** * @dev Initializes the relayer depositor * @param config Task config * @param _relayer Relayer address */ function initialize(TaskConfig memory config, address _relayer) external virtual initializer { __RelayerDepositor_init(config, _relayer); } /** * @dev Initializes the relayer depositor. It does call upper contracts initializers. * @param config Task config * @param _relayer Relayer address */ function __RelayerDepositor_init(TaskConfig memory config, address _relayer) internal onlyInitializing { __Task_init(config); __RelayerDepositor_init_unchained(config, _relayer); } /** * @dev Initializes the relayer depositor. It does not call upper contracts initializers. * @param _relayer Relayer address */ function __RelayerDepositor_init_unchained(TaskConfig memory, address _relayer) internal onlyInitializing { _setRelayer(_relayer); } /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function setRelayer(address newRelayer) external override authP(authParams(newRelayer)) { _setRelayer(newRelayer); } /** * @dev Executes the relayer depositor task */ function call(address token, uint256 amount) external override authP(authParams(token, amount)) { if (amount == 0) amount = getTaskAmount(token); _beforeRelayerDepositor(token, amount); bytes memory relayerData = abi.encodeWithSelector(IRelayer.deposit.selector, smartVault, amount); // solhint-disable-next-line avoid-low-level-calls ISmartVault(smartVault).call(relayer, relayerData, amount); _afterRelayerDepositor(token, amount); } /** * @dev Before relayer depositor hook */ function _beforeRelayerDepositor(address token, uint256 amount) internal virtual { _beforeTask(token, amount); if (amount == 0) revert TaskAmountZero(); } /** * @dev After relayer depositor hook */ function _afterRelayerDepositor(address token, uint256 amount) internal virtual { _afterTask(token, amount); } /** * @dev Sets the relayer * @param newRelayer Address of the relayer to be set */ function _setRelayer(address newRelayer) internal { if (newRelayer == address(0)) revert TaskRelayerZero(); relayer = newRelayer; emit RelayerSet(newRelayer); } }
// 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 './BaseRelayerFundTask.sol'; import '../primitives/Unwrapper.sol'; /** * @title Unwrapper relayer funder * @dev Task used to convert funds in order to pay relayers using an unwrapper */ contract UnwrapperRelayerFunder is BaseRelayerFundTask, Unwrapper { /** * @dev Disables the default unwrapper initializer */ function initialize(UnwrapConfig memory) external pure override { revert TaskInitializerDisabled(); } /** * @dev Initializes the unwrapper relayer funder * @param config Unwrap config * @param relayer Relayer address */ function initializeUnwrapperRelayerFunder(UnwrapConfig memory config, address relayer) external virtual initializer { __UnwrapperRelayerFunder_init(config, relayer); } /** * @dev Initializes the unwrapper relayer funder. It does call upper contracts initializers. * @param config Unwrap config * @param relayer Relayer address */ function __UnwrapperRelayerFunder_init(UnwrapConfig memory config, address relayer) internal onlyInitializing { __Unwrapper_init(config); __BaseRelayerFundTask_init_unchained(BaseRelayerFundConfig(relayer, config.taskConfig)); __UnwrapperRelayerFunder_init_unchained(config, relayer); } /** * @dev Initializes the unwrapper relayer funder. It does not call upper contracts initializers. * @param config Unwrap config * @param relayer Relayer address */ function __UnwrapperRelayerFunder_init_unchained(UnwrapConfig memory config, address relayer) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Tells the `token` amount to be funded * @param token Address of the token to be used to fund the relayer */ function getTaskAmount(address token) public view override(BaseRelayerFundTask, IBaseTask, BaseTask) returns (uint256) { return BaseRelayerFundTask.getTaskAmount(token); } /** * @dev Before token threshold task hook */ function _beforeTokenThresholdTask(address token, uint256 amount) internal override(BaseRelayerFundTask, TokenThresholdTask) { BaseRelayerFundTask._beforeTokenThresholdTask(token, amount); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2Vault.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2SwapConnector.sol'; import './BalancerV2BptSwapper.sol'; import '../interfaces/liquidity/balancer/IBalancerBoostedPool.sol'; /** * @title Balancer v2 boosted swapper task * @dev Task that extends the Balancer v2 BPT swapper task specially for boosted pools */ contract BalancerV2BoostedSwapper is BalancerV2BptSwapper { /** * @dev Tells the token out that should be used for a token. In case there is no token out defined for the * requested token, it will use one of the underlying pool tokens. */ function getTokenOut(address token) public view virtual override(IBaseSwapTask, BaseSwapTask) returns (address) { address tokenOut = BaseSwapTask.getTokenOut(token); if (tokenOut != address(0)) return tokenOut; bytes32 poolId = IBalancerBoostedPool(token).getPoolId(); uint256 bptIndex = IBalancerBoostedPool(token).getBptIndex(); address balancerV2Vault = IBalancerV2SwapConnector(connector).balancerV2Vault(); (IERC20[] memory tokens, , ) = IBalancerV2Vault(balancerV2Vault).getPoolTokens(poolId); return address(bptIndex == 0 ? tokens[1] : tokens[0]); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2SwapConnector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IBalancerV2BptSwapper.sol'; import '../interfaces/liquidity/balancer/IBalancerPool.sol'; /** * @title Balancer v2 BPT swapper task * @dev Task that extends the swapper task to use Balancer v2 */ contract BalancerV2BptSwapper is IBalancerV2BptSwapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('BALANCER_V2_BPT_SWAPPER'); /** * @dev Balancer v2 BPT swap config. Only used in the initializer. */ struct BalancerV2BptSwapConfig { BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the Balancer v2 BPT swapper * @param config Balancer v2 BPT swap config */ function initialize(BalancerV2BptSwapConfig memory config) external initializer { __BalancerV2BptSwapper_init(config); } /** * @dev Initializes the Balancer v2 BPT swapper. It does call upper contracts. * @param config Balancer v2 BPT swap config */ function __BalancerV2BptSwapper_init(BalancerV2BptSwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __BalancerV2BptSwapper_init_unchained(config); } /** * @dev Initializes the Balancer v2 BPT swapper. It does not call upper contracts. * @param config Balancer v2 BPT swap config */ function __BalancerV2BptSwapper_init_unchained(BalancerV2BptSwapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the Balancer v2 BPT swapper task */ function call(address tokenIn, uint256 amountIn, uint256 slippage) external override authP(authParams(tokenIn, amountIn, slippage)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); _beforeBalancerV2BptSwapper(tokenIn, amountIn, slippage); address tokenOut = getTokenOut(tokenIn); uint256 price = _getPrice(tokenIn, tokenOut); uint256 minAmountOut = amountIn.mulUp(price).mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IBalancerV2SwapConnector.execute.selector, tokenIn, tokenOut, amountIn, minAmountOut, IBalancerPool(tokenIn).getPoolId(), new bytes32[](0), new address[](0) ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterBalancerV2BptSwapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256()); } /** * @dev Before Balancer v2 BPT swapper task */ function _beforeBalancerV2BptSwapper(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseSwapTask(token, amount, slippage); } /** * @dev After Balancer v2 BPT swapper hook */ function _afterBalancerV2BptSwapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/balancer/IBalancerV2SwapConnector.sol'; import './BalancerV2BptSwapper.sol'; import '../interfaces/liquidity/balancer/IBalancerLinearPool.sol'; /** * @title Balancer v2 linear swapper task * @dev Task that extends the Balancer v2 BPT swapper task specially for linear pools */ contract BalancerV2LinearSwapper is BalancerV2BptSwapper { /** * @dev Tells the token out that should be used for a token. In case there is no token out defined for the * requested token, it will use the linear pool main token. */ function getTokenOut(address token) public view virtual override(IBaseSwapTask, BaseSwapTask) returns (address) { address tokenOut = BaseSwapTask.getTokenOut(token); if (tokenOut != address(0)) return tokenOut; return IBalancerLinearPool(token).getMainToken(); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/Denominations.sol'; import '../Task.sol'; import '../interfaces/swap/IBaseSwapTask.sol'; /** * @title Base swap task * @dev Task that offers the basic components for more detailed swap tasks */ abstract contract BaseSwapTask is IBaseSwapTask, Task { using FixedPoint for uint256; // Connector address address public override connector; // Default token out address public override defaultTokenOut; // Default maximum slippage in fixed point uint256 public override defaultMaxSlippage; // Token out per token mapping (address => address) public override customTokenOut; // Maximum slippage per token address mapping (address => uint256) public override customMaxSlippage; /** * @dev Custom token out config. Only used in the initializer. */ struct CustomTokenOut { address token; address tokenOut; } /** * @dev Custom max slippage config. Only used in the initializer. */ struct CustomMaxSlippage { address token; uint256 maxSlippage; } /** * @dev Base swap config. Only used in the initializer. */ struct BaseSwapConfig { address connector; address tokenOut; uint256 maxSlippage; CustomTokenOut[] customTokensOut; CustomMaxSlippage[] customMaxSlippages; TaskConfig taskConfig; } /** * @dev Initializes the base swap task. It does call upper contracts initializers. * @param config Base swap config */ function __BaseSwapTask_init(BaseSwapConfig memory config) internal onlyInitializing { __Task_init(config.taskConfig); __BaseSwapTask_init_unchained(config); } /** * @dev Initializes the base swap task. It does not call upper contracts initializers. * @param config Base swap config */ function __BaseSwapTask_init_unchained(BaseSwapConfig memory config) internal onlyInitializing { _setConnector(config.connector); _setDefaultTokenOut(config.tokenOut); _setDefaultMaxSlippage(config.maxSlippage); for (uint256 i = 0; i < config.customTokensOut.length; i++) { _setCustomTokenOut(config.customTokensOut[i].token, config.customTokensOut[i].tokenOut); } for (uint256 i = 0; i < config.customMaxSlippages.length; i++) { _setCustomMaxSlippage(config.customMaxSlippages[i].token, config.customMaxSlippages[i].maxSlippage); } } /** * @dev Tells the token out that should be used for a token */ function getTokenOut(address token) public view virtual override returns (address) { address tokenOut = customTokenOut[token]; return tokenOut == address(0) ? defaultTokenOut : tokenOut; } /** * @dev Tells the max slippage that should be used for a token */ function getMaxSlippage(address token) public view virtual override returns (uint256) { uint256 maxSlippage = customMaxSlippage[token]; return maxSlippage == 0 ? defaultMaxSlippage : maxSlippage; } /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function setConnector(address newConnector) external override authP(authParams(newConnector)) { _setConnector(newConnector); } /** * @dev Sets the default token out * @param tokenOut Address of the default token out to be set */ function setDefaultTokenOut(address tokenOut) external override authP(authParams(tokenOut)) { _setDefaultTokenOut(tokenOut); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function setDefaultMaxSlippage(uint256 maxSlippage) external override authP(authParams(maxSlippage)) { _setDefaultMaxSlippage(maxSlippage); } /** * @dev Sets a custom token out * @param token Address of the token to set a custom token out for * @param tokenOut Address of the token out to be set */ function setCustomTokenOut(address token, address tokenOut) external override authP(authParams(token, tokenOut)) { _setCustomTokenOut(token, tokenOut); } /** * @dev Sets a custom max slippage * @param token Address of the token to set a custom max slippage for * @param maxSlippage Max slippage to be set */ function setCustomMaxSlippage(address token, uint256 maxSlippage) external override authP(authParams(token, maxSlippage)) { _setCustomMaxSlippage(token, maxSlippage); } /** * @dev Before base swap task hook */ function _beforeBaseSwapTask(address token, uint256 amount, uint256 slippage) internal virtual { _beforeTask(token, amount); if (token == address(0)) revert TaskTokenZero(); if (amount == 0) revert TaskAmountZero(); if (getTokenOut(token) == address(0)) revert TaskTokenOutNotSet(); uint256 maxSlippage = getMaxSlippage(token); if (slippage > maxSlippage) revert TaskSlippageAboveMax(slippage, maxSlippage); } /** * @dev After base swap task hook */ function _afterBaseSwapTask(address tokenIn, uint256 amountIn, uint256, address tokenOut, uint256 amountOut) internal virtual { _increaseBalanceConnector(tokenOut, amountOut); _afterTask(tokenIn, amountIn); } /** * @dev Sets a new connector * @param newConnector Address of the connector to be set */ function _setConnector(address newConnector) internal { if (newConnector == address(0)) revert TaskConnectorZero(); connector = newConnector; emit ConnectorSet(newConnector); } /** * @dev Sets the default token out * @param tokenOut Default token out to be set */ function _setDefaultTokenOut(address tokenOut) internal { defaultTokenOut = tokenOut; emit DefaultTokenOutSet(tokenOut); } /** * @dev Sets the default max slippage * @param maxSlippage Default max slippage to be set */ function _setDefaultMaxSlippage(uint256 maxSlippage) internal { if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); defaultMaxSlippage = maxSlippage; emit DefaultMaxSlippageSet(maxSlippage); } /** * @dev Sets a custom token out for a token * @param token Address of the token to set the custom token out for * @param tokenOut Address of the token out to be set */ function _setCustomTokenOut(address token, address tokenOut) internal { if (token == address(0)) revert TaskTokenZero(); customTokenOut[token] = tokenOut; emit CustomTokenOutSet(token, tokenOut); } /** * @dev Sets a custom max slippage for a token * @param token Address of the token to set the custom max slippage for * @param maxSlippage Max slippage to be set */ function _setCustomMaxSlippage(address token, uint256 maxSlippage) internal { if (token == address(0)) revert TaskTokenZero(); if (maxSlippage > FixedPoint.ONE) revert TaskSlippageAboveOne(); customMaxSlippage[token] = maxSlippage; emit CustomMaxSlippageSet(token, maxSlippage); } }
// 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-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/hop/IHopL2Amm.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/hop/IHopSwapConnector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IHopL2Swapper.sol'; /** * @title Hop L2 swapper * @dev Task that extends the base swap task to use Hop */ contract HopL2Swapper is IHopL2Swapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('HOP_L2_SWAPPER'); // List of AMMs per token mapping (address => address) public override tokenAmm; /** * @dev Token amm config. Only used in the initializer. */ struct TokenAmm { address token; address amm; } /** * @dev Hop L2 swap config. Only used in the initializer. */ struct HopL2SwapConfig { TokenAmm[] tokenAmms; BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the Hop L2 swapper * @param config Hop L2 swap config */ function initialize(HopL2SwapConfig memory config) external virtual initializer { __HopL2Swapper_init(config); } /** * @dev Initializes the Hop L2 swapper. It does call upper contracts initializers. * @param config Hop L2 swap config */ function __HopL2Swapper_init(HopL2SwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __HopL2Swapper_init_unchained(config); } /** * @dev Initializes the Hop L2 swapper. It does not call upper contracts initializers. * @param config Hop L2 swap config */ function __HopL2Swapper_init_unchained(HopL2SwapConfig memory config) internal onlyInitializing { for (uint256 i = 0; i < config.tokenAmms.length; i++) { _setTokenAmm(config.tokenAmms[i].token, config.tokenAmms[i].amm); } } /** * @dev Sets an AMM for a hToken * @param hToken Address of the hToken to be set * @param amm AMM address to be set for the hToken */ function setTokenAmm(address hToken, address amm) external authP(authParams(hToken, amm)) { _setTokenAmm(hToken, amm); } /** * @dev Execution function */ function call(address hToken, uint256 amount, uint256 slippage) external override authP(authParams(hToken, amount, slippage)) { if (amount == 0) amount = getTaskAmount(hToken); _beforeHopL2Swapper(hToken, amount, slippage); address tokenOut = getTokenOut(hToken); address dexAddress = IHopL2Amm(tokenAmm[hToken]).exchangeAddress(); uint256 minAmountOut = amount.mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IHopSwapConnector.execute.selector, hToken, tokenOut, amount, minAmountOut, dexAddress ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterHopL2Swapper(hToken, amount, slippage, tokenOut, result.toUint256()); } /** * @dev Before Hop L2 swapper hook */ function _beforeHopL2Swapper(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseSwapTask(token, amount, slippage); if (tokenAmm[token] == address(0)) revert TaskMissingHopTokenAmm(); } /** * @dev After Hop L2 swapper hook */ function _afterHopL2Swapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } /** * @dev Set an AMM for a Hop token * @param hToken Address of the hToken to set an AMM for * @param amm AMM to be set */ function _setTokenAmm(address hToken, address amm) internal { if (hToken == address(0)) revert TaskTokenZero(); if (amm != address(0) && hToken != IHopL2Amm(amm).hToken()) revert TaskHopTokenAmmMismatch(hToken, amm); tokenAmm[hToken] = amm; emit TokenAmmSet(hToken, amm); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/1inch/IOneInchV5Connector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IOneInchV5Swapper.sol'; /** * @title 1inch v5 swapper * @dev Task that extends the base swap task to use 1inch v5 */ contract OneInchV5Swapper is IOneInchV5Swapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('1INCH_V5_SWAPPER'); /** * @dev 1inch v5 swap config. Only used in the initializer. */ struct OneInchV5SwapConfig { BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the 1inch v5 swapper * @param config 1inch v5 swap config */ function initialize(OneInchV5SwapConfig memory config) external virtual initializer { __OneInchV5Swapper_init(config); } /** * @dev Initializes the 1inch v5 swapper. It does call upper contracts initializers. * @param config 1inch v5 swap config */ function __OneInchV5Swapper_init(OneInchV5SwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __OneInchV5Swapper_init_unchained(config); } /** * @dev Initializes the 1inch v5 swapper. It does not call upper contracts initializers. * @param config 1inch v5 swap config */ function __OneInchV5Swapper_init_unchained(OneInchV5SwapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the 1inch V5 swapper task */ function call(address tokenIn, uint256 amountIn, uint256 slippage, bytes memory data) external override authP(authParams(tokenIn, amountIn, slippage)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); _beforeOneInchV5Swapper(tokenIn, amountIn, slippage); address tokenOut = getTokenOut(tokenIn); uint256 price = _getPrice(tokenIn, tokenOut); uint256 minAmountOut = amountIn.mulUp(price).mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IOneInchV5Connector.execute.selector, tokenIn, tokenOut, amountIn, minAmountOut, data ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterOneInchV5Swapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256()); } /** * @dev Before 1inch v5 swapper hook */ function _beforeOneInchV5Swapper(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseSwapTask(token, amount, slippage); } /** * @dev After 1inch v5 swapper hook */ function _afterOneInchV5Swapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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/utils/cryptography/ECDSA.sol'; import '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/paraswap/IParaswapV5Connector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IParaswapV5Swapper.sol'; /** * @title Paraswap V5 swapper task * @dev Task that extends the swapper task to use Paraswap v5 */ contract ParaswapV5Swapper is IParaswapV5Swapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('PARASWAP_V5_SWAPPER'); // Address of the Paraswap quote signer address public override quoteSigner; /** * @dev Paraswap v5 swap config. Only used in the initializer. */ struct ParaswapV5SwapConfig { address quoteSigner; BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the Paraswap v5 swapper * @param config Paraswap v5 swap config */ function initialize(ParaswapV5SwapConfig memory config) external virtual initializer { __ParaswapV5Swapper_init(config); } /** * @dev Initializes the Paraswap v5 swapper. It does call upper contracts initializers. * @param config Paraswap v5 swap config */ function __ParaswapV5Swapper_init(ParaswapV5SwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __ParaswapV5Swapper_init_unchained(config); } /** * @dev Initializes the Paraswap v5 swapper. It does not call upper contracts initializers. * @param config Paraswap v5 swap config */ function __ParaswapV5Swapper_init_unchained(ParaswapV5SwapConfig memory config) internal onlyInitializing { _setQuoteSigner(config.quoteSigner); } /** * @dev Sets the quote signer address * @param newQuoteSigner Address of the new quote signer to be set */ function setQuoteSigner(address newQuoteSigner) external override authP(authParams(newQuoteSigner)) { _setQuoteSigner(newQuoteSigner); } /** * @dev Execute Paraswap v5 swapper task */ function call( address tokenIn, uint256 amountIn, uint256 minAmountOut, uint256 expectedAmountOut, uint256 deadline, bytes memory data, bytes memory sig ) external override authP(authParams(tokenIn, amountIn, minAmountOut, expectedAmountOut, deadline)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); address tokenOut = getTokenOut(tokenIn); uint256 slippage = FixedPoint.ONE - minAmountOut.divUp(expectedAmountOut); _beforeParaswapV5Swapper( tokenIn, tokenOut, amountIn, slippage, minAmountOut, expectedAmountOut, deadline, data, sig ); bytes memory connectorData = abi.encodeWithSelector( IParaswapV5Connector.execute.selector, tokenIn, tokenOut, amountIn, minAmountOut, data ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterParaswapV5Swapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256()); } /** * @dev Before Paraswap v5 swapper hook */ function _beforeParaswapV5Swapper( address tokenIn, address tokenOut, uint256 amountIn, uint256 slippage, uint256 minAmountOut, uint256 expectedAmountOut, uint256 deadline, bytes memory data, bytes memory sig ) internal virtual { _beforeBaseSwapTask(tokenIn, amountIn, slippage); bool isBuy = false; bytes32 message = keccak256( abi.encodePacked(tokenIn, tokenOut, isBuy, amountIn, minAmountOut, expectedAmountOut, deadline, data) ); address signer = ECDSA.recover(ECDSA.toEthSignedMessageHash(message), sig); if (signer != quoteSigner) revert TaskInvalidQuoteSigner(signer, quoteSigner); if (block.timestamp > deadline) revert TaskQuoteSignerPastDeadline(deadline, block.timestamp); } /** * @dev After Paraswap v5 swapper hook */ function _afterParaswapV5Swapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } /** * @dev Sets the quote signer address * @param newQuoteSigner Address of the new quote signer to be set */ function _setQuoteSigner(address newQuoteSigner) internal { if (newQuoteSigner == address(0)) revert TaskQuoteSignerZero(); quoteSigner = newQuoteSigner; emit QuoteSignerSet(newQuoteSigner); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/uniswap/IUniswapV2Connector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IUniswapV2Swapper.sol'; /** * @title Uniswap v2 swapper * @dev Task that extends the base swap task to use Uniswap v2 */ contract UniswapV2Swapper is IUniswapV2Swapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('UNISWAP_V2_SWAPPER'); /** * @dev Uniswap v2 swap config. Only used in the initializer. */ struct UniswapV2SwapConfig { BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the Uniswap v2 swapper * @param config Uniswap v2 swap config */ function initialize(UniswapV2SwapConfig memory config) external initializer { __UniswapV2Swapper_init(config); } /** * @dev Initializes the Uniswap v2 swapper. It does call upper contracts. * @param config Uniswap v2 swap config */ function __UniswapV2Swapper_init(UniswapV2SwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __UniswapV2Swapper_init_unchained(config); } /** * @dev Initializes the Uniswap v2 swapper. It does not call upper contracts. * @param config Uniswap v2 swap config */ function __UniswapV2Swapper_init_unchained(UniswapV2SwapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the Uniswap v2 swapper task */ function call(address tokenIn, uint256 amountIn, uint256 slippage, address[] memory hopTokens) external override authP(authParams(tokenIn, amountIn, slippage)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); _beforeUniswapV2Swapper(tokenIn, amountIn, slippage); address tokenOut = getTokenOut(tokenIn); uint256 price = _getPrice(tokenIn, tokenOut); uint256 minAmountOut = amountIn.mulUp(price).mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IUniswapV2Connector.execute.selector, tokenIn, tokenOut, amountIn, minAmountOut, hopTokens ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterUniswapV2Swapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256()); } /** * @dev Before Uniswap v2 swapper hook */ function _beforeUniswapV2Swapper(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseSwapTask(token, amount, slippage); } /** * @dev After Uniswap v2 swapper hook */ function _afterUniswapV2Swapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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-helpers/contracts/math/FixedPoint.sol'; import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol'; import '@mimic-fi/v3-connectors/contracts/interfaces/uniswap/IUniswapV3Connector.sol'; import './BaseSwapTask.sol'; import '../interfaces/swap/IUniswapV3Swapper.sol'; /** * @title Uniswap v3 swapper task * @dev Task that extends the swapper task to use Uniswap v3 */ contract UniswapV3Swapper is IUniswapV3Swapper, BaseSwapTask { using FixedPoint for uint256; using BytesHelpers for bytes; // Execution type for relayers bytes32 public constant override EXECUTION_TYPE = keccak256('UNISWAP_V3_SWAPPER'); /** * @dev Uniswap v3 swap config. Only used in the initializer. */ struct UniswapV3SwapConfig { BaseSwapConfig baseSwapConfig; } /** * @dev Initializes the Uniswap v3 swapper * @param config Uniswap v3 swap config */ function initialize(UniswapV3SwapConfig memory config) external initializer { __UniswapV3Swapper_init(config); } /** * @dev Initializes the Uniswap V3 swapper. It does call upper contracts. * @param config Uniswap v3 swap config */ function __UniswapV3Swapper_init(UniswapV3SwapConfig memory config) internal onlyInitializing { __BaseSwapTask_init(config.baseSwapConfig); __UniswapV3Swapper_init_unchained(config); } /** * @dev Initializes the Uniswap V3 swapper. It does not call upper contracts. * @param config Uniswap v3 swap config */ function __UniswapV3Swapper_init_unchained(UniswapV3SwapConfig memory config) internal onlyInitializing { // solhint-disable-previous-line no-empty-blocks } /** * @dev Executes the Uniswap v3 swapper task */ function call( address tokenIn, uint256 amountIn, uint256 slippage, uint24 fee, address[] memory hopTokens, uint24[] memory hopFees ) external override authP(authParams(tokenIn, amountIn, slippage, fee)) { if (amountIn == 0) amountIn = getTaskAmount(tokenIn); _beforeUniswapV3Swapper(tokenIn, amountIn, slippage); address tokenOut = getTokenOut(tokenIn); uint256 price = _getPrice(tokenIn, tokenOut); uint256 minAmountOut = amountIn.mulUp(price).mulUp(FixedPoint.ONE - slippage); bytes memory connectorData = abi.encodeWithSelector( IUniswapV3Connector.execute.selector, tokenIn, tokenOut, amountIn, minAmountOut, fee, hopTokens, hopFees ); bytes memory result = ISmartVault(smartVault).execute(connector, connectorData); _afterUniswapV3Swapper(tokenIn, amountIn, slippage, tokenOut, result.toUint256()); } /** * @dev Before Uniswap v3 swapper task */ function _beforeUniswapV3Swapper(address token, uint256 amount, uint256 slippage) internal virtual { _beforeBaseSwapTask(token, amount, slippage); } /** * @dev After Uniswap v3 swapper hook */ function _afterUniswapV3Swapper( address tokenIn, uint256 amountIn, uint256 slippage, address tokenOut, uint256 amountOut ) internal virtual { _afterBaseSwapTask(tokenIn, amountIn, slippage, tokenOut, amountOut); } }
// 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 pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; contract BaseTaskMock is BaseTask { bytes32 public constant override EXECUTION_TYPE = keccak256('BASE_TASK'); function initialize(BaseConfig memory config) external virtual initializer { __BaseTask_init(config); } function call(address token, uint256 amount) external { _beforeBaseTask(token, amount); _afterBaseTask(token, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/GasLimitedTask.sol'; contract GasLimitedTaskMock is BaseTask, GasLimitedTask { bytes32 public constant override EXECUTION_TYPE = keccak256('GAS_LIMITED_TASK'); struct GasLimitMockConfig { BaseConfig baseConfig; GasLimitConfig gasLimitConfig; } function initialize(GasLimitMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __GasLimitedTask_init(config.gasLimitConfig); } function call(address token, uint256 amount) external { _beforeGasLimitedTaskMock(token, amount); _afterGasLimitedTaskMock(token, amount); } /** * @dev Fetches a base/quote price */ function _getPrice(address base, address quote) internal view override(BaseTask, GasLimitedTask) returns (uint256) { return BaseTask._getPrice(base, quote); } /** * @dev Before gas limited task mock hook */ function _beforeGasLimitedTaskMock(address token, uint256 amount) internal virtual { _beforeBaseTask(token, amount); _beforeGasLimitedTask(token, amount); } /** * @dev After gas limited task mock hook */ function _afterGasLimitedTaskMock(address token, uint256 amount) internal virtual { _afterGasLimitedTask(token, amount); _afterBaseTask(token, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/PausableTask.sol'; contract PausableTaskMock is BaseTask, PausableTask { bytes32 public constant override EXECUTION_TYPE = keccak256('PAUSABLE_TASK'); struct PauseMockConfig { BaseConfig baseConfig; } function initialize(PauseMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __PausableTask_init(); } function call(address token, uint256 amount) external { if (amount == 0) amount = getTaskAmount(token); _beforePausableTaskMock(token, amount); _afterPausableTaskMock(token, amount); } /** * @dev Before pausable task mock hook */ function _beforePausableTaskMock(address token, uint256 amount) internal virtual { _beforeBaseTask(token, amount); _beforePausableTask(token, amount); } /** * @dev After pausable task mock hook */ function _afterPausableTaskMock(address token, uint256 amount) internal virtual { _afterPausableTask(token, amount); _afterBaseTask(token, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/TimeLockedTask.sol'; contract TimeLockedTaskMock is BaseTask, TimeLockedTask { bytes32 public constant override EXECUTION_TYPE = keccak256('TIME_LOCKED_TASK'); struct TimeLockMockConfig { BaseConfig baseConfig; TimeLockConfig timeLockConfig; } function initialize(TimeLockMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __TimeLockedTask_init(config.timeLockConfig); } function call() external { _beforeTimeLockedTaskMock(); _afterTimeLockedTaskMock(); } /** * @dev Before time locked task mock hook */ function _beforeTimeLockedTaskMock() internal virtual { _beforeBaseTask(address(0), 0); _beforeTimeLockedTask(address(0), 0); } /** * @dev After time locked task mock hook */ function _afterTimeLockedTaskMock() internal virtual { _afterTimeLockedTask(address(0), 0); _afterBaseTask(address(0), 0); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/TokenIndexedTask.sol'; contract TokenIndexedTaskMock is BaseTask, TokenIndexedTask { using EnumerableSet for EnumerableSet.AddressSet; bytes32 public constant override EXECUTION_TYPE = keccak256('TOKEN_INDEXED_TASK'); struct TokenIndexMockConfig { BaseConfig baseConfig; TokenIndexConfig tokenIndexConfig; } function initialize(TokenIndexMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __TokenIndexedTask_init(config.tokenIndexConfig); } function call(address token) external { _beforeTokenIndexedTaskMock(token); _afterTokenIndexedTaskMock(token); } /** * @dev Before token indexed task mock hook */ function _beforeTokenIndexedTaskMock(address token) internal virtual { _beforeBaseTask(token, 0); _beforeTokenIndexedTask(token, 0); } /** * @dev After token indexed task mock hook */ function _afterTokenIndexedTaskMock(address token) internal virtual { _afterTokenIndexedTask(token, 0); _afterBaseTask(token, 0); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/TokenThresholdTask.sol'; contract TokenThresholdTaskMock is BaseTask, TokenThresholdTask { bytes32 public constant override EXECUTION_TYPE = keccak256('TOKEN_THRESHOLD_TASK'); struct TokenThresholdMockConfig { BaseConfig baseConfig; TokenThresholdConfig tokenThresholdConfig; } function initialize(TokenThresholdMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __TokenThresholdTask_init(config.tokenThresholdConfig); } function call(address token, uint256 amount) external { _beforeTokenThresholdTask(token, amount); _afterTokenThresholdTask(token, amount); } /** * @dev Fetches a base/quote price */ function _getPrice(address base, address quote) internal view override(BaseTask, TokenThresholdTask) returns (uint256) { return BaseTask._getPrice(base, quote); } /** * @dev Before token threshold task mock hook */ function _beforeTokenThresholdTaskMock(address token, uint256 amount) internal virtual { _beforeBaseTask(token, amount); _beforeTokenThresholdTask(token, amount); } /** * @dev After token threshold task mock hook */ function _afterTokenThresholdTaskMock(address token, uint256 amount) internal virtual { _afterTokenThresholdTask(token, amount); _afterBaseTask(token, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../../base/BaseTask.sol'; import '../../base/VolumeLimitedTask.sol'; contract VolumeLimitedTaskMock is BaseTask, VolumeLimitedTask { bytes32 public constant override EXECUTION_TYPE = keccak256('VOLUME_LIMITED_TASK'); struct VolumeLimitMockConfig { BaseConfig baseConfig; VolumeLimitConfig volumeLimitConfig; } function initialize(VolumeLimitMockConfig memory config) external virtual initializer { __BaseTask_init(config.baseConfig); __VolumeLimitedTask_init(config.volumeLimitConfig); } function call(address token, uint256 amount) external { _beforeVolumeLimitedTaskMock(token, amount); _afterVolumeLimitedTaskMock(token, amount); } /** * @dev Fetches a base/quote price */ function _getPrice(address base, address quote) internal view override(BaseTask, VolumeLimitedTask) returns (uint256) { return BaseTask._getPrice(base, quote); } /** * @dev Before volume limited task mock hook */ function _beforeVolumeLimitedTaskMock(address token, uint256 amount) internal virtual { _beforeBaseTask(token, amount); _beforeVolumeLimitedTask(token, amount); } /** * @dev After volume limited task mock hook */ function _afterVolumeLimitedTaskMock(address token, uint256 amount) internal virtual { _afterVolumeLimitedTask(token, amount); _afterBaseTask(token, amount); } }
// 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; contract AxelarConnectorMock { event LogExecute(uint256 chainId, address token, uint256 amount, address recipient); function execute(uint256 chainId, address token, uint256 amount, address recipient) external { emit LogExecute(chainId, token, amount, recipient); } }
// 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; contract ConnextConnectorMock { event LogExecute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, uint256 relayerFee ); function execute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, uint256 relayerFee ) external { emit LogExecute(chainId, token, amount, minAmountOut, recipient, relayerFee); } }
// 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; contract HopBridgeConnectorMock { event LogExecute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, address bridge, uint256 deadline, address relayer, uint256 fee ); function execute( uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient, address bridge, uint256 deadline, address relayer, uint256 fee ) external { emit LogExecute(chainId, token, amount, minAmountOut, recipient, bridge, deadline, relayer, fee); } }
// 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; contract WormholeConnectorMock { event LogExecute(uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient); function execute(uint256 chainId, address token, uint256 amount, uint256 minAmountOut, address recipient) external { emit LogExecute(chainId, token, amount, minAmountOut, recipient); } }
// 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. pragma solidity ^0.8.0; contract BalancerV2PoolConnectorMock { address public immutable balancerV2Vault; constructor(address _balancerV2Vault) { balancerV2Vault = _balancerV2Vault; } event LogExecute(address tokenIn, uint256 amountIn, address[] tokensOut, uint256[] minAmountsOut); function exit(address tokenIn, uint256 amountIn, address[] memory tokensOut, uint256[] memory minAmountsOut) external returns (uint256[] memory amountsOut) { emit LogExecute(tokenIn, amountIn, tokensOut, minAmountsOut); return minAmountsOut; } }
// 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-helpers/contracts/mocks/TokenMock.sol'; contract ConvexConnectorMock { IERC20 public immutable rewardToken; uint256 public immutable rewardAmount; constructor() { rewardAmount = 5e18; rewardToken = new TokenMock('Convex Claimer Reward', 18); } mapping (address => address) public getCvxPool; mapping (address => address) public getCurvePool; event LogClaim(address cvxPool); event LogJoin(address curvePool, uint256 amount); event LogExit(address cvxPool, uint256 amount); function setCvxPool(address curvePool, address cvxPool) external { getCvxPool[curvePool] = cvxPool; } function setCurvePool(address cvxPool, address curvePool) external { getCurvePool[cvxPool] = curvePool; } function claim(address cvxPool) external returns (address[] memory tokens, uint256[] memory amounts) { tokens = new address[](1); tokens[0] = address(rewardToken); amounts = new uint256[](1); amounts[0] = rewardAmount; emit LogClaim(cvxPool); } function join(address curvePool, uint256 amount) external returns (uint256) { emit LogJoin(curvePool, amount); return amount; } function exit(address cvxPool, uint256 amount) external returns (uint256) { emit LogExit(cvxPool, amount); return amount; } }
// 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; contract Curve2CrvConnectorMock { event LogJoin(address pool, address tokenIn, uint256 amountIn, uint256 slippage); event LogExit(address pool, uint256 amountIn, address tokenOut, uint256 slippage); function join(address pool, address tokenIn, uint256 amountIn, uint256 slippage) external returns (uint256) { emit LogJoin(pool, tokenIn, amountIn, slippage); return amountIn; } function exit(address pool, uint256 amountIn, address tokenOut, uint256 slippage) external returns (uint256) { emit LogExit(pool, amountIn, tokenOut, slippage); return amountIn; } }
// 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; contract ERC4626ConnectorMock { address public immutable tokenOut; event LogJoin(address erc4626, address token, uint256 amount, uint256 minAmountOut); event LogExit(address erc4626, uint256 amount, uint256 minAmountOut); constructor(address _tokenOut) { tokenOut = _tokenOut; } function join(address erc4626, address token, uint256 assets, uint256 minSharesOut) external returns (address, uint256) { emit LogJoin(erc4626, token, assets, minSharesOut); return (erc4626, minSharesOut); } function exit(address erc4626, uint256 shares, uint256 minAssetsOut) external returns (address, uint256) { emit LogExit(erc4626, shares, minAssetsOut); return (tokenOut, minAssetsOut); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract HopL2AmmMock { address public immutable hToken; address public immutable l2CanonicalToken; constructor(address _token, address _hToken) { l2CanonicalToken = _token; hToken = _hToken; } function exchangeAddress() external view returns (address) { return address(this); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract RelayerMock { event Deposited(address smartVault, uint256 amount); mapping (address => uint256) public getSmartVaultBalance; mapping (address => uint256) public getSmartVaultUsedQuota; function deposit(address smartVault, uint256 amount) external payable { getSmartVaultBalance[smartVault] += amount; emit Deposited(smartVault, amount); } function setSmartVaultUsedQuota(address smartVault, uint256 quota) external { getSmartVaultUsedQuota[smartVault] = quota; } }
// 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. pragma solidity ^0.8.0; contract BalancerV2SwapConnectorMock { address public immutable balancerV2Vault; constructor(address _balancerV2Vault) { balancerV2Vault = _balancerV2Vault; } event LogExecute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes32 poolId, bytes32[] hopPoolsIds, address[] hopTokens ); function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes32 poolId, bytes32[] memory hopPoolsIds, address[] memory hopTokens ) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, poolId, hopPoolsIds, hopTokens); return minAmountOut; } }
// 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; contract HopSwapConnectorMock { event LogExecute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address hopDexAddress); function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address hopDexAddress) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, hopDexAddress); return minAmountOut; } }
// 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; contract OneInchV5ConnectorMock { event LogExecute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes data); function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, data); return minAmountOut; } }
// 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; contract ParaswapV5ConnectorMock { event LogExecute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes data); function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, data); return minAmountOut; } }
// 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; contract UniswapV2ConnectorMock { event LogExecute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address[] hopTokens); function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address[] memory hopTokens ) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, hopTokens); return minAmountOut; } }
// 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. pragma solidity ^0.8.0; contract UniswapV3ConnectorMock { event LogExecute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint24 fee, address[] hopTokens, uint24[] hopFees ); function execute( address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint24 fee, address[] memory hopTokens, uint24[] memory hopFees ) external returns (uint256) { emit LogExecute(tokenIn, tokenOut, amountIn, minAmountOut, fee, hopTokens, hopFees); return minAmountOut; } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"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":"TaskAmountZero","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":[],"name":"TaskValueZero","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":"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":"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":[{"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":"taskConfig","type":"tuple"}],"internalType":"struct Depositor.DepositConfig","name":"config","type":"tuple"}],"name":"initialize","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":"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"},{"stateMutability":"payable","type":"receive"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 1.53% | $1 | 1,602.0418 | $1,602.04 | |
ETH | 1.44% | $0.683086 | 2,200.5413 | $1,503.16 | |
ETH | 1.41% | $1.14 | 1,291.0551 | $1,471.8 | |
ETH | 1.37% | $1 | 1,426.5901 | $1,426.59 | |
ETH | 1.16% | $1,907.54 | 0.634 | $1,209.41 | |
ETH | 1.16% | $0.666132 | 1,811.664 | $1,206.81 | |
ETH | 1.12% | $0.000014 | 85,205,936.3264 | $1,168.17 | |
ETH | 1.09% | $0.217859 | 5,219.2841 | $1,137.07 | |
ETH | 1.07% | $0.936009 | 1,191.6066 | $1,115.35 | |
ETH | 1.07% | $1,804.98 | 0.6172 | $1,114.03 | |
ETH | 1.03% | $0.298619 | 3,597.5561 | $1,074.3 | |
ETH | 1.03% | $2,163.92 | 0.4959 | $1,073.17 | |
ETH | 0.98% | $1.12 | 912.25 | $1,021.72 | |
ETH | 0.96% | $15 | 66.8336 | $1,002.5 | |
ETH | 0.91% | $5,124.9 | 0.1848 | $947.06 | |
ETH | 0.87% | $0.999616 | 912.7405 | $912.39 | |
ETH | 0.84% | $9.55 | 91.7392 | $876.46 | |
ETH | 0.84% | $2,034.33 | 0.4305 | $875.74 | |
ETH | 0.83% | $0.010813 | 79,666.5181 | $861.4 | |
ETH | 0.82% | $0.999914 | 853.3408 | $853.27 | |
ETH | 0.79% | $1,960.03 | 0.4224 | $827.89 | |
ETH | 0.78% | $0.642947 | 1,264.0609 | $812.72 | |
ETH | 0.77% | $0.870146 | 929.6138 | $808.9 | |
ETH | 0.77% | $0.163672 | 4,915.4566 | $804.52 | |
ETH | 0.74% | $0.139186 | 5,582.1609 | $776.96 | |
ETH | 0.74% | $0.024897 | 31,090.2063 | $774.05 | |
ETH | 0.74% | $0.044972 | 17,177.3944 | $772.5 | |
ETH | 0.73% | $1,801.33 | 0.4232 | $762.31 | |
ETH | 0.72% | $0.999983 | 755.8726 | $755.86 | |
ETH | 0.72% | $1.19 | 631.3529 | $751.31 | |
ETH | 0.68% | $165.63 | 4.3105 | $713.94 | |
ETH | 0.67% | $17.36 | 40.2051 | $697.96 | |
ETH | 0.65% | $1 | 680.5162 | $681.2 | |
ETH | 0.65% | $0.091779 | 7,385.1895 | $677.81 | |
ETH | 0.64% | $0.299657 | 2,217.4141 | $664.46 | |
ETH | 0.63% | $1,804.98 | 0.3654 | $659.57 | |
ETH | 0.62% | $0.007032 | 91,844.2971 | $645.84 | |
ETH | 0.61% | $0.024795 | 25,839.4046 | $640.69 | |
ETH | 0.59% | $0.561522 | 1,095.7694 | $615.3 | |
ETH | 0.58% | $0.076018 | 7,967.4963 | $605.67 | |
ETH | 0.58% | $0.000001 | 1,033,636,760.1289 | $603.07 | |
ETH | 0.58% | $0.017611 | 34,170.0934 | $601.78 | |
ETH | 0.56% | $6.05 | 97.1491 | $587.75 | |
ETH | 0.55% | $19.37 | 29.4041 | $569.56 | |
ETH | 0.54% | $0.091464 | 6,157.1903 | $563.16 | |
ETH | 0.54% | $0.148748 | 3,772.2357 | $561.11 | |
ETH | 0.54% | $0.176683 | 3,170.1342 | $560.11 | |
ETH | 0.53% | $0.272519 | 2,015.1549 | $549.17 | |
ETH | 0.52% | $1,803.6 | 0.3029 | $546.34 | |
ETH | 0.52% | $1,508.64 | 0.3591 | $541.71 | |
ETH | 0.50% | $0.392441 | 1,317.1114 | $516.89 | |
ETH | 0.49% | $0.804692 | 639.4808 | $514.59 | |
ETH | 0.48% | $7.82 | 63.6777 | $497.96 | |
ETH | 0.48% | $3.12 | 159.4153 | $497.38 | |
ETH | 0.47% | $3,347.64 | 0.1461 | $489.11 | |
ETH | 0.46% | $0.0352 | 13,631.6116 | $479.84 | |
ETH | 0.46% | $0.349623 | 1,369.8947 | $478.95 | |
ETH | 0.44% | $0.31351 | 1,467.2271 | $459.99 | |
ETH | 0.44% | $1,802.62 | 0.2549 | $459.48 | |
ETH | 0.44% | $0.001518 | 302,003.076 | $458.48 | |
ETH | 0.44% | $15.5 | 29.5127 | $457.45 | |
ETH | 0.41% | $0.508804 | 846.8116 | $430.86 | |
ETH | 0.40% | $0.999166 | 421.904 | $421.55 | |
ETH | 0.39% | $0.14821 | 2,734.028 | $405.21 | |
ETH | 0.38% | $21.76 | 18.2941 | $398.08 | |
ETH | 0.38% | $0.71068 | 559.8712 | $397.89 | |
ETH | 0.36% | $0.023138 | 16,251.7409 | $376.04 | |
ETH | 0.36% | $0.065866 | 5,678.714 | $374.03 | |
ETH | 0.36% | $2,002.72 | 0.1856 | $371.66 | |
ETH | 0.35% | $0.027313 | 13,432.1184 | $366.87 | |
ETH | 0.35% | $0.18886 | 1,909.6057 | $360.65 | |
ETH | 0.33% | $43.45 | 8.0254 | $348.7 | |
ETH | 0.32% | $1 | 339.0031 | $339 | |
ETH | 0.32% | $0.999397 | 339.19 | $338.99 | |
ETH | 0.32% | $2.49 | 133.5284 | $332.49 | |
ETH | 0.31% | $0.019702 | 16,654.9288 | $328.14 | |
ETH | 0.31% | $0.267648 | 1,194.4477 | $319.69 | |
ETH | 0.30% | <$0.000001 | 27,383,991,733.7978 | $318.09 | |
ETH | 0.30% | $0.406957 | 781.3262 | $317.97 | |
ETH | 0.29% | $0.271664 | 1,118.837 | $303.95 | |
ETH | 0.28% | $0.162563 | 1,775.1433 | $288.57 | |
ETH | 0.27% | $0.779521 | 366.3872 | $285.61 | |
ETH | 0.27% | $0.214922 | 1,325.3613 | $284.85 | |
ETH | 0.27% | $0.149 | 1,909.4436 | $284.51 | |
ETH | 0.27% | $2.99 | 94.0859 | $281.32 | |
ETH | 0.26% | $0.001079 | 252,380.6768 | $272.29 | |
ETH | 0.26% | $0.109623 | 2,466.9121 | $270.43 | |
ETH | 0.26% | $0.999553 | 269.8314 | $269.71 | |
ETH | 0.25% | $2.85 | 90.502 | $257.67 | |
ETH | 0.24% | $114.16 | 2.2183 | $253.25 | |
ETH | 0.23% | $0.002147 | 113,879.4919 | $244.52 | |
ETH | 0.23% | $0.735823 | 330.5286 | $243.21 | |
ETH | 0.23% | $0.090533 | 2,678.8147 | $242.52 | |
ETH | 0.23% | $0.004402 | 54,578.6575 | $240.24 | |
ETH | 0.23% | $0.016626 | 14,435.4398 | $240.01 | |
ETH | 0.22% | $0.06987 | 3,296.0199 | $230.29 | |
ETH | 0.22% | $71.7 | 3.2012 | $229.53 | |
ETH | 0.22% | $611.62 | 0.3752 | $229.49 | |
ETH | 0.22% | $0.893638 | 256.0538 | $228.82 | |
ETH | 0.22% | $1,867.31 | 0.1217 | $227.25 | |
ETH | 0.21% | $0.331168 | 677.2928 | $224.3 | |
ETH | 0.21% | $0.05291 | 4,228.211 | $223.71 | |
ETH | 0.21% | $0.668428 | 329.5774 | $220.3 | |
ETH | 0.21% | $0.113311 | 1,938.4864 | $219.65 | |
ETH | 0.21% | $0.000016 | 13,646,977.5918 | $219.03 | |
ETH | 0.21% | $0.000473 | 457,684.1393 | $216.33 | |
ETH | 0.20% | $0.016408 | 12,898.2197 | $211.64 | |
ETH | 0.20% | $1,923.97 | 0.107 | $205.84 | |
ETH | 0.20% | $4.58 | 44.6422 | $204.46 | |
ETH | 0.20% | $0.110682 | 1,845.8908 | $204.31 | |
ETH | 0.19% | $1.06 | 190 | $201.02 | |
ETH | 0.19% | $16.02 | 12.4092 | $198.8 | |
ETH | 0.19% | $0.240122 | 805.6624 | $193.46 | |
ETH | 0.18% | $0.004174 | 45,963.0849 | $191.84 | |
ETH | 0.18% | $0.211705 | 905.6503 | $191.73 | |
ETH | 0.18% | <$0.000001 | 4,419,326,052.9262 | $191.49 | |
ETH | 0.18% | $0.519596 | 361.8187 | $188 | |
ETH | 0.17% | $0.31512 | 561.8318 | $177.04 | |
ETH | 0.17% | $1 | 176.7959 | $176.8 | |
ETH | 0.17% | $0.33277 | 528.7055 | $175.94 | |
ETH | 0.16% | $1.07 | 161.6079 | $172.16 | |
ETH | 0.16% | $0.212213 | 774.0544 | $164.26 | |
ETH | 0.16% | <$0.000001 | 3,163,850,564.0302 | $163.68 | |
ETH | 0.16% | $93,678 | 0.00174059 | $163.05 | |
ETH | 0.15% | $0.222594 | 711.922 | $158.47 | |
ETH | 0.15% | $0.5126 | 297.1314 | $152.31 | |
ETH | 0.15% | $4.54 | 33.4123 | $151.69 | |
ETH | 0.14% | $2.89 | 52.0848 | $150.52 | |
ETH | 0.14% | $0.028377 | 5,197.7891 | $147.5 | |
ETH | 0.14% | $0.006365 | 23,086.5546 | $146.95 | |
ETH | 0.14% | $5.62 | 25.7971 | $144.98 | |
ETH | 0.14% | $15.8 | 9.0065 | $142.34 | |
ETH | 0.13% | $0.567424 | 247.519 | $140.45 | |
ETH | 0.13% | $0.063551 | 2,209.4547 | $140.41 | |
ETH | 0.13% | $0.000062 | 2,264,313.4558 | $139.87 | |
ETH | 0.13% | $0.05113 | 2,685.6981 | $137.32 | |
ETH | 0.13% | $3.24 | 42.234 | $136.84 | |
ETH | 0.13% | $36.26 | 3.744 | $135.76 | |
ETH | 0.13% | $0.12039 | 1,122.9279 | $135.19 | |
ETH | 0.13% | $0.422275 | 318.2328 | $134.38 | |
ETH | 0.13% | $39.25 | 3.4235 | $134.37 | |
ETH | 0.13% | $0.007349 | 18,072.3322 | $132.81 | |
ETH | 0.13% | $0.629696 | 210.8448 | $132.77 | |
ETH | 0.12% | $0.186486 | 699.2927 | $130.41 | |
ETH | 0.12% | $1 | 129.2 | $129.2 | |
ETH | 0.12% | $0.022461 | 5,646.2911 | $126.82 | |
ETH | 0.12% | $0.809414 | 156.3141 | $126.52 | |
ETH | 0.12% | $0.015615 | 8,073.4809 | $126.07 | |
ETH | 0.12% | $1.52 | 80.1861 | $121.88 | |
ETH | 0.12% | $0.000584 | 207,499.6955 | $121.14 | |
ETH | 0.12% | $0.015767 | 7,637.0848 | $120.42 | |
ETH | 0.11% | $0.221445 | 539.9458 | $119.57 | |
ETH | 0.11% | $0.000581 | 204,582.5 | $118.78 | |
ETH | 0.11% | $0.053591 | 2,194.3073 | $117.6 | |
ETH | 0.11% | $336.16 | 0.3458 | $116.26 | |
ETH | 0.11% | $1,979.05 | 0.0585 | $115.86 | |
ETH | 0.11% | $0.062127 | 1,856.9174 | $115.37 | |
ETH | 0.11% | $0.142532 | 798.1844 | $113.77 | |
ETH | 0.11% | $0.826338 | 135.4563 | $111.93 | |
ETH | 0.11% | $0.686252 | 160.6315 | $110.23 | |
ETH | 0.10% | $0.674228 | 160.5128 | $108.22 | |
ETH | 0.10% | $0.044901 | 2,386.2514 | $107.14 | |
ETH | 0.10% | <$0.000001 | 2,610,617,445.719 | $107.13 | |
ETH | 0.10% | $0.319037 | 333.9968 | $106.56 | |
ETH | 0.10% | $0.08411 | 1,266.2416 | $106.5 | |
ETH | 0.10% | $0.418246 | 254.3365 | $106.38 | |
ETH | 0.10% | $0.644343 | 164.5471 | $106.02 | |
ETH | 0.10% | $0.355813 | 296.0697 | $105.35 | |
ETH | 0.10% | $0.000048 | 2,204,593.4522 | $105.18 | |
ETH | 0.10% | $0.961018 | 109.375 | $105.11 | |
ETH | 0.10% | $0.278081 | 371.8158 | $103.39 | |
ETH | 0.10% | $0.558732 | 181.4605 | $101.39 | |
ETH | 0.10% | $0.346929 | 287.8438 | $99.86 | |
ETH | 0.09% | $0.104046 | 950.4966 | $98.9 | |
ETH | 0.09% | <$0.000001 | 15,407,985,361.5731 | $97.95 | |
ETH | 0.09% | $0.301577 | 323.5377 | $97.57 | |
ETH | 0.09% | $0.041437 | 2,349.0451 | $97.34 | |
ETH | 0.09% | $0.019162 | 4,949.0094 | $94.83 | |
ETH | 0.09% | $0.118293 | 764.6813 | $90.46 | |
ETH | 0.09% | $0.273167 | 330.54 | $90.29 | |
ETH | 0.09% | $8 | 11.2014 | $89.61 | |
ETH | 0.08% | $0.051733 | 1,688.5009 | $87.35 | |
ETH | 0.08% | $0.002417 | 36,040.7113 | $87.11 | |
ETH | 0.08% | $0.01688 | 5,159.9249 | $87.1 | |
ETH | 0.08% | $0.123612 | 677.0169 | $83.69 | |
ETH | 0.08% | $0.066904 | 1,250.4397 | $83.66 | |
ETH | 0.08% | $0.065545 | 1,274.6187 | $83.55 | |
ETH | 0.08% | $0.999937 | 81.67 | $81.66 | |
ETH | 0.08% | $0.106035 | 750.9993 | $79.63 | |
ETH | 0.08% | $0.066631 | 1,188.5438 | $79.19 | |
ETH | 0.07% | $0.789437 | 98.1154 | $77.46 | |
ETH | 0.07% | <$0.000001 | 347,939,871.2687 | $76.62 | |
ETH | 0.07% | $0.00946 | 8,061.6924 | $76.26 | |
ETH | 0.07% | $3.49 | 21.6619 | $75.6 | |
ETH | 0.07% | $0.313631 | 240.1838 | $75.33 | |
ETH | 0.07% | $0.013708 | 5,251.2506 | $71.98 | |
ETH | 0.07% | $9.36 | 7.5095 | $70.29 | |
ETH | 0.07% | $0.02818 | 2,489.622 | $70.16 | |
ETH | 0.07% | $57.16 | 1.214 | $69.39 | |
ETH | 0.07% | $0.108932 | 636.5847 | $69.34 | |
ETH | 0.06% | $1,927.36 | 0.0346 | $66.63 | |
ETH | 0.06% | $8.17 | 7.9854 | $65.24 | |
ETH | 0.06% | $0.000909 | 71,359.6606 | $64.86 | |
ETH | 0.06% | $0.087546 | 737.5794 | $64.57 | |
ETH | 0.06% | $0.317404 | 199.4037 | $63.29 | |
ETH | 0.06% | $2.19 | 28.859 | $63.2 | |
ETH | 0.06% | $0.483092 | 127.9957 | $61.83 | |
ETH | 0.06% | $0.03689 | 1,674.576 | $61.77 | |
ETH | 0.06% | $0.08451 | 725.3193 | $61.3 | |
ETH | 0.06% | $0.092439 | 653.2145 | $60.38 | |
ETH | 0.06% | $0.01716 | 3,490.3945 | $59.9 | |
ETH | 0.06% | $0.002155 | 26,808.9813 | $57.77 | |
ETH | 0.05% | $0.00004 | 1,369,850.0125 | $55.2 | |
ETH | 0.05% | $1 | 54.629 | $54.89 | |
ETH | 0.05% | $0.111397 | 488.995 | $54.47 | |
ETH | 0.05% | $0.114426 | 472.1302 | $54.02 | |
ETH | 0.05% | $0.000069 | 769,011.9309 | $53.18 | |
ETH | 0.05% | $0.024857 | 2,117.2161 | $52.63 | |
ETH | 0.05% | $2.26 | 23.2603 | $52.57 | |
ETH | 0.05% | $2.71 | 19.2809 | $52.25 | |
ETH | 0.05% | $0.313303 | 163.5613 | $51.24 | |
ETH | 0.05% | $153 | 0.3321 | $50.81 | |
ETH | 0.05% | $0.016954 | 2,989.4136 | $50.68 | |
ETH | 0.05% | <$0.000001 | 106,810,558.2976 | $50.05 | |
ETH | 0.05% | $0.000023 | 2,152,028.5169 | $49.71 | |
ETH | 0.05% | $2.45 | 20.1481 | $49.36 | |
ETH | 0.05% | $0.99945 | 48.9277 | $48.9 | |
ETH | 0.05% | $73.38 | 0.6606 | $48.47 | |
ETH | 0.05% | $0.027288 | 1,737.8046 | $47.42 | |
ETH | 0.05% | $0.141577 | 331.8907 | $46.99 | |
ETH | 0.04% | $0.036675 | 1,273 | $46.69 | |
ETH | 0.04% | $0.006239 | 7,435.8 | $46.39 | |
ETH | 0.04% | $0.06243 | 742.8432 | $46.38 | |
ETH | 0.04% | $0.243124 | 188.2392 | $45.77 | |
ETH | 0.04% | $0.004423 | 10,288.7862 | $45.51 | |
ETH | 0.04% | $161.56 | 0.2809 | $45.38 | |
ETH | 0.04% | $0.09151 | 493.782 | $45.19 | |
ETH | 0.04% | $0.185113 | 241.6028 | $44.72 | |
ETH | 0.04% | $0.078943 | 564.6658 | $44.58 | |
ETH | 0.04% | $0.1482 | 291.8888 | $43.26 | |
ETH | 0.04% | $0.008815 | 4,878.3323 | $43 | |
ETH | 0.04% | $0.052681 | 783.1439 | $41.26 | |
ETH | 0.04% | $1.22 | 33.714 | $41.13 | |
ETH | 0.04% | $0.007431 | 5,533.4802 | $41.12 | |
ETH | 0.04% | $0.000005 | 8,658,484.4907 | $40.96 | |
ETH | 0.04% | $0.004023 | 10,155.6937 | $40.85 | |
ETH | 0.04% | $0.979697 | 41.46 | $40.62 | |
ETH | 0.04% | $0.99992 | 40.2792 | $40.28 | |
ETH | 0.04% | $0.002292 | 17,307.9047 | $39.66 | |
ETH | 0.04% | $0.05944 | 662.6983 | $39.39 | |
ETH | 0.04% | $0.344318 | 111.0882 | $38.25 | |
ETH | 0.04% | $0.000938 | 40,420.3454 | $37.93 | |
ETH | 0.04% | $0.091403 | 411.8491 | $37.64 | |
ETH | 0.04% | <$0.000001 | 267,881,729.3707 | $37.53 | |
ETH | 0.04% | $0.011566 | 3,241.7382 | $37.49 | |
ETH | 0.04% | $0.00182 | 20,482 | $37.29 | |
ETH | 0.04% | $14.98 | 2.4504 | $36.71 | |
ETH | 0.03% | $0.811843 | 44.611 | $36.22 | |
ETH | 0.03% | <$0.000001 | 283,222,868.0739 | $36.18 | |
ETH | 0.03% | $0.00018 | 194,419.6476 | $34.96 | |
ETH | 0.03% | $0.095 | 365.3104 | $34.7 | |
ETH | 0.03% | $0.029687 | 1,163.1183 | $34.53 | |
ETH | 0.03% | <$0.000001 | 22,854,844,293.8656 | $34.44 | |
ETH | 0.03% | $0.000582 | 58,949.3911 | $34.29 | |
ETH | 0.03% | $0.227248 | 144.0159 | $32.73 | |
ETH | 0.03% | $0.001523 | 21,432.2888 | $32.65 | |
ETH | 0.03% | $0.067708 | 481.6081 | $32.61 | |
ETH | 0.03% | $2.54 | 12.7773 | $32.45 | |
ETH | 0.03% | $0.398057 | 81.4385 | $32.42 | |
ETH | 0.03% | $0.013814 | 2,346.2796 | $32.41 | |
ETH | 0.03% | $0.023094 | 1,395.5051 | $32.23 | |
ETH | 0.03% | $0.018203 | 1,762.1752 | $32.08 | |
ETH | 0.03% | $0.034872 | 917.4897 | $32 | |
ETH | 0.03% | $0.016831 | 1,900 | $31.98 | |
ETH | 0.03% | $0.023611 | 1,353.6448 | $31.96 | |
ETH | 0.03% | $0.000202 | 157,498.9845 | $31.75 | |
ETH | 0.03% | $0.092212 | 342.8906 | $31.62 | |
ETH | 0.03% | $1,858.22 | 0.017 | $31.6 | |
ETH | 0.03% | $0.001706 | 18,185 | $31.02 | |
ETH | 0.03% | $0.006096 | 5,046.1361 | $30.76 | |
ETH | 0.03% | $0.219267 | 139.1441 | $30.51 | |
ETH | 0.03% | $0.000241 | 124,090.2134 | $29.88 | |
ETH | 0.03% | $0.647602 | 45.9515 | $29.76 | |
ETH | 0.03% | $0.237456 | 125.1115 | $29.71 | |
ETH | 0.03% | $4.42 | 6.65 | $29.39 | |
ETH | 0.03% | $0.000516 | 56,595.9933 | $29.2 | |
ETH | 0.03% | $3,066.35 | 0.0095 | $29.13 | |
ETH | 0.03% | $0.074971 | 384.9689 | $28.86 | |
ETH | 0.03% | $0.001478 | 19,428.6061 | $28.72 | |
ETH | 0.03% | $5,901.8 | 0.00486486 | $28.71 | |
ETH | 0.03% | $0.114157 | 250.9662 | $28.65 | |
ETH | 0.03% | $0.027967 | 1,018.0512 | $28.47 | |
ETH | 0.03% | $0.170687 | 163.5908 | $27.92 | |
ETH | 0.03% | $0.07787 | 355.6228 | $27.69 | |
ETH | 0.03% | $0.000579 | 46,966.0449 | $27.18 | |
ETH | 0.03% | $0.435197 | 62.2809 | $27.1 | |
ETH | 0.03% | $0.312721 | 84.0512 | $26.28 | |
ETH | 0.03% | $0.01474 | 1,779.5099 | $26.23 | |
ETH | 0.02% | $0.009381 | 2,755.852 | $25.85 | |
ETH | 0.02% | $0.059171 | 432.4244 | $25.59 | |
ETH | 0.02% | $1.31 | 19.4393 | $25.54 | |
ETH | 0.02% | $0.205895 | 123.7162 | $25.47 | |
ETH | 0.02% | $0.59912 | 42.3088 | $25.35 | |
ETH | 0.02% | $0.201744 | 125.0463 | $25.23 | |
ETH | 0.02% | $1,845.28 | 0.0137 | $25.22 | |
ETH | 0.02% | $0.011053 | 2,261.7326 | $25 | |
ETH | 0.02% | $1.21 | 20.517 | $24.83 | |
ETH | 0.02% | $1,885.83 | 0.0132 | $24.82 | |
ETH | 0.02% | $0.367301 | 67.417 | $24.76 | |
ETH | 0.02% | $0.000001 | 17,279,853.2046 | $24.7 | |
ETH | 0.02% | $0.00378 | 6,522.0582 | $24.65 | |
ETH | 0.02% | $0.840356 | 29.3113 | $24.63 | |
ETH | 0.02% | $0.00048 | 51,137.3975 | $24.56 | |
ETH | 0.02% | $0.02451 | 986.5519 | $24.18 | |
ETH | 0.02% | $22.97 | 1.0523 | $24.17 | |
ETH | 0.02% | $0.000066 | 364,591.029 | $24.06 | |
ETH | 0.02% | $1.87 | 12.6277 | $23.61 | |
ETH | 0.02% | $1.21 | 19.4077 | $23.49 | |
ETH | 0.02% | <$0.000001 | 71,568,413.2705 | $23.33 | |
ETH | 0.02% | $0.001729 | 13,225.8635 | $22.87 | |
ETH | 0.02% | $29.13 | 0.7691 | $22.4 | |
ETH | 0.02% | $0.006648 | 3,349.6057 | $22.27 | |
ETH | 0.02% | $0.000217 | 102,516.7233 | $22.25 | |
ETH | 0.02% | $1,794.75 | 0.0123 | $22.13 | |
ETH | 0.02% | $612.26 | 0.036 | $22.07 | |
ETH | 0.02% | $0.999768 | 22.0422 | $22.04 | |
ETH | 0.02% | $0.010675 | 2,061.5 | $22.01 | |
ETH | 0.02% | $0.126656 | 173.468 | $21.97 | |
ETH | 0.02% | $0.08227 | 265.136 | $21.81 | |
ETH | 0.02% | $0.014274 | 1,520 | $21.7 | |
ETH | 0.02% | $0.000319 | 67,685.275 | $21.61 | |
ETH | 0.02% | $0.00912 | 2,351.2602 | $21.44 | |
ETH | 0.02% | $0.797046 | 26.791 | $21.35 | |
ETH | 0.02% | $0.000562 | 38,000 | $21.35 | |
ETH | 0.02% | $0.058035 | 366.4364 | $21.27 | |
ETH | 0.02% | $0.000009 | 2,293,813.8166 | $21.19 | |
ETH | 0.02% | $7.78 | 2.7152 | $21.12 | |
ETH | 0.02% | $0.367313 | 56.5574 | $20.77 | |
ETH | 0.02% | $0.0013 | 15,971.0212 | $20.76 | |
ETH | 0.02% | $0.029344 | 705.485 | $20.7 | |
ETH | 0.02% | $0.000005 | 4,600,085.6917 | $20.7 | |
ETH | 0.02% | $0.039931 | 514.8483 | $20.56 | |
ETH | 0.02% | $0.060675 | 337.2204 | $20.46 | |
ETH | 0.02% | $0.000738 | 26,945.6812 | $19.89 | |
ETH | 0.02% | $0.000001 | 18,478,726.8848 | $19.77 | |
ETH | 0.02% | $30.1 | 0.6506 | $19.59 | |
ETH | 0.02% | $2.03 | 9.4766 | $19.24 | |
ETH | 0.02% | $2.1 | 9.0181 | $18.94 | |
ETH | 0.02% | $0.083092 | 225.7634 | $18.76 | |
ETH | 0.02% | $0.009395 | 1,976.2659 | $18.57 | |
ETH | 0.02% | $0.014631 | 1,251.4577 | $18.31 | |
ETH | 0.02% | $0.016706 | 1,092.5 | $18.25 | |
ETH | 0.02% | $94,978 | 0.00019 | $18.05 | |
ETH | 0.02% | $0.696065 | 25.4239 | $17.7 | |
ETH | 0.02% | $0.308942 | 57.0959 | $17.64 | |
ETH | 0.02% | $0.725683 | 24.2658 | $17.61 | |
ETH | 0.02% | $0.591034 | 29.777 | $17.6 | |
ETH | 0.02% | $0.208393 | 84.148 | $17.54 | |
ETH | 0.02% | $0.001972 | 8,872.7952 | $17.49 | |
ETH | 0.02% | $0.044863 | 386.9714 | $17.36 | |
ETH | 0.02% | $0.000177 | 95,599.1991 | $16.93 | |
ETH | 0.02% | $0.001217 | 13,831.7375 | $16.83 | |
ETH | 0.02% | $0.000001 | 30,506,624.0124 | $16.79 | |
ETH | 0.02% | $0.364589 | 43.9312 | $16.02 | |
ETH | 0.01% | $0.001675 | 9,306.0098 | $15.59 | |
ETH | 0.01% | $0.098058 | 158.7008 | $15.56 | |
ETH | 0.01% | $0.043199 | 355.1807 | $15.34 | |
ETH | 0.01% | $8.86 | 1.7228 | $15.27 | |
ETH | 0.01% | $0.724671 | 20.9237 | $15.16 | |
ETH | 0.01% | $0.024185 | 623.1029 | $15.07 | |
ETH | 0.01% | $0.136728 | 109.5796 | $14.98 | |
ETH | 0.01% | $0.000801 | 18,690.1814 | $14.98 | |
ETH | 0.01% | $0.024797 | 595.6011 | $14.77 | |
ETH | 0.01% | $0.278004 | 52.4569 | $14.58 | |
ETH | 0.01% | <$0.000001 | 9,572,523,836.6963 | $14.08 | |
ETH | 0.01% | $0.010651 | 1,315.4462 | $14.01 | |
ETH | 0.01% | $1.16 | 11.9454 | $13.86 | |
ETH | 0.01% | $17.68 | 0.7815 | $13.82 | |
ETH | 0.01% | $0.000013 | 1,045,000 | $13.72 | |
ETH | 0.01% | $1.34 | 10.1508 | $13.6 | |
ETH | 0.01% | $0.763037 | 17.423 | $13.29 | |
ETH | 0.01% | $0.112648 | 117.5767 | $13.24 | |
ETH | 0.01% | $0.23454 | 56.0772 | $13.15 | |
ETH | 0.01% | $0.20084 | 64.401 | $12.93 | |
ETH | 0.01% | $0.040017 | 321.0359 | $12.85 | |
ETH | 0.01% | $0.621922 | 20.5203 | $12.76 | |
ETH | 0.01% | $0.300655 | 41.9587 | $12.62 | |
ETH | 0.01% | $0.093019 | 133.0532 | $12.38 | |
ETH | 0.01% | $0.117895 | 104.5263 | $12.32 | |
ETH | 0.01% | $4.68 | 2.6323 | $12.32 | |
ETH | 0.01% | $0.000847 | 14,520.7023 | $12.31 | |
ETH | 0.01% | $0.019684 | 622.2244 | $12.25 | |
ETH | 0.01% | $0.109608 | 107.6756 | $11.8 | |
ETH | 0.01% | $0.032494 | 354.2097 | $11.51 | |
ETH | 0.01% | $0.00001 | 1,179,073.8137 | $11.45 | |
ETH | 0.01% | $0.001907 | 5,984.3298 | $11.41 | |
ETH | 0.01% | $0.555859 | 20.4224 | $11.35 | |
ETH | 0.01% | $0.015823 | 717.3547 | $11.35 | |
ETH | 0.01% | $0.2143 | 52.0679 | $11.16 | |
ETH | 0.01% | $0.035069 | 318.1201 | $11.16 | |
ETH | 0.01% | $0.089702 | 124.0178 | $11.12 | |
ETH | 0.01% | $0.024561 | 442.9851 | $10.88 | |
ETH | 0.01% | $0.375191 | 28.4949 | $10.69 | |
ETH | 0.01% | $0.21538 | 48.8795 | $10.53 | |
ETH | 0.01% | $0.007357 | 1,427.9638 | $10.51 | |
ETH | <0.01% | $0.012144 | 855 | $10.38 | |
ETH | <0.01% | $0.009324 | 1,106.0084 | $10.31 | |
ETH | <0.01% | $0.000877 | 11,700.0632 | $10.26 | |
ETH | <0.01% | $0.094959 | 107.7741 | $10.23 | |
ETH | <0.01% | $1.21 | 8.3589 | $10.11 | |
ETH | <0.01% | $0.027676 | 363.5512 | $10.06 | |
ETH | <0.01% | $0.049186 | 203.687 | $10.02 | |
ETH | <0.01% | $0.008903 | 1,115.0637 | $9.93 | |
ETH | <0.01% | $0.032626 | 300.6592 | $9.81 | |
ETH | <0.01% | $0.0004 | 24,424.1072 | $9.76 | |
ETH | <0.01% | $0.001451 | 6,717.2287 | $9.75 | |
ETH | <0.01% | $0.008336 | 1,168.8809 | $9.74 | |
ETH | <0.01% | $0.023374 | 412.9415 | $9.65 | |
ETH | <0.01% | $0.000003 | 3,303,971.0063 | $9.65 | |
ETH | <0.01% | $1.52 | 6.344 | $9.64 | |
ETH | <0.01% | $0.001568 | 6,129.7168 | $9.61 | |
ETH | <0.01% | $0.000001 | 14,889,660.2871 | $9.59 | |
ETH | <0.01% | $0.012779 | 749.8311 | $9.58 | |
ETH | <0.01% | $0.995965 | 9.5 | $9.46 | |
ETH | <0.01% | $0.032006 | 294.091 | $9.41 | |
ETH | <0.01% | $0.000087 | 108,474.1379 | $9.38 | |
ETH | <0.01% | $0.019784 | 472.1805 | $9.34 | |
ETH | <0.01% | $0.001004 | 9,289.7994 | $9.32 | |
ETH | <0.01% | $0.014105 | 659.5643 | $9.3 | |
ETH | <0.01% | $0.055921 | 165.6618 | $9.26 | |
ETH | <0.01% | $0.073334 | 124.1016 | $9.1 | |
ETH | <0.01% | $0.001763 | 5,120.1137 | $9.03 | |
ETH | <0.01% | $0.068124 | 130.3725 | $8.88 | |
ETH | <0.01% | $0.006152 | 1,437.5899 | $8.84 | |
ETH | <0.01% | $0.003881 | 2,268.5164 | $8.8 | |
ETH | <0.01% | $0.005215 | 1,677.0159 | $8.75 | |
ETH | <0.01% | $0.632975 | 13.8031 | $8.74 | |
ETH | <0.01% | $0.013068 | 666.4146 | $8.71 | |
ETH | <0.01% | <$0.000001 | 85,266,774,567.7041 | $8.63 | |
ETH | <0.01% | $0.344575 | 24.9783 | $8.61 | |
ETH | <0.01% | $0.794235 | 10.8254 | $8.6 | |
ETH | <0.01% | $0.612198 | 13.9642 | $8.55 | |
ETH | <0.01% | $0.145979 | 57.4327 | $8.38 | |
ETH | <0.01% | <$0.000001 | 236,339,374.5212 | $8.32 | |
ETH | <0.01% | $2.99 | 2.7425 | $8.2 | |
ETH | <0.01% | $0.421425 | 19.2806 | $8.13 | |
ETH | <0.01% | $0.035756 | 222.0625 | $7.94 | |
ETH | <0.01% | $0.00002 | 399,000 | $7.89 | |
ETH | <0.01% | $0.022171 | 354.9264 | $7.87 | |
ETH | <0.01% | $0.000022 | 351,504.8537 | $7.77 | |
ETH | <0.01% | $0.007731 | 1,004.5168 | $7.77 | |
ETH | <0.01% | $0.011551 | 670.405 | $7.74 | |
ETH | <0.01% | <$0.000001 | 474,793,042,270,338.63 | $7.74 | |
ETH | <0.01% | $0.021295 | 362.5484 | $7.72 | |
ETH | <0.01% | $0.000099 | 76,531.2022 | $7.56 | |
ETH | <0.01% | $0.002938 | 2,565.3352 | $7.54 | |
ETH | <0.01% | $0.059459 | 124.9568 | $7.43 | |
ETH | <0.01% | $0.031061 | 238.7388 | $7.42 | |
ETH | <0.01% | $0.03727 | 191.8433 | $7.15 | |
ETH | <0.01% | $0.016395 | 433.3425 | $7.1 | |
ETH | <0.01% | $0.018021 | 390.3136 | $7.03 | |
ETH | <0.01% | $0.058405 | 118.6666 | $6.93 | |
ETH | <0.01% | $4.86 | 1.4206 | $6.9 | |
ETH | <0.01% | $0.009222 | 738.5318 | $6.81 | |
ETH | <0.01% | $0.000213 | 31,666.6635 | $6.74 | |
ETH | <0.01% | $0.000001 | 10,545,408.785 | $6.74 | |
ETH | <0.01% | $0.002006 | 3,327.9339 | $6.68 | |
ETH | <0.01% | $10.31 | 0.6434 | $6.64 | |
ETH | <0.01% | $0.000177 | 36,986.8362 | $6.56 | |
ETH | <0.01% | $0.920525 | 7.0823 | $6.52 | |
ETH | <0.01% | $0.001694 | 3,823.3981 | $6.48 | |
ETH | <0.01% | $0.03582 | 179.2832 | $6.42 | |
ETH | <0.01% | $0.794359 | 8.0536 | $6.4 | |
ETH | <0.01% | $0.000092 | 68,466.7178 | $6.33 | |
ETH | <0.01% | $0.009967 | 634.98 | $6.33 | |
ETH | <0.01% | $0.020137 | 312.1991 | $6.29 | |
ETH | <0.01% | $0.01665 | 375.259 | $6.25 | |
ETH | <0.01% | $0.016761 | 371.5096 | $6.23 | |
ETH | <0.01% | $1.8 | 3.4396 | $6.2 | |
ETH | <0.01% | $0.1071 | 57.2178 | $6.13 | |
ETH | <0.01% | $0.007728 | 792.0553 | $6.12 | |
ETH | <0.01% | $0.004691 | 1,302.6136 | $6.11 | |
ETH | <0.01% | <$0.000001 | 13,095,005,290.2093 | $6 | |
ETH | <0.01% | $0.001931 | 3,099.2507 | $5.98 | |
ETH | <0.01% | $0.331617 | 18.0203 | $5.98 | |
ETH | <0.01% | <$0.000001 | 1,921,811,040.2838 | $5.97 | |
ETH | <0.01% | $0.00522 | 1,130.9523 | $5.9 | |
ETH | <0.01% | $0.006001 | 979.9944 | $5.88 | |
ETH | <0.01% | $0.036283 | 160.3332 | $5.82 | |
ETH | <0.01% | $1 | 5.7429 | $5.77 | |
ETH | <0.01% | $0.064982 | 88.0181 | $5.72 | |
ETH | <0.01% | <$0.000001 | 22,928,646.8641 | $5.64 | |
ETH | <0.01% | $0.021629 | 260.6193 | $5.64 | |
ETH | <0.01% | $0.983666 | 5.6903 | $5.6 | |
ETH | <0.01% | $0.000001 | 9,268,624.2508 | $5.57 | |
ETH | <0.01% | $0.320345 | 17.1846 | $5.51 | |
ETH | <0.01% | $0.006176 | 890.9949 | $5.5 | |
ETH | <0.01% | $0.249275 | 21.8149 | $5.44 | |
ETH | <0.01% | <$0.000001 | 79,379,571.6347 | $5.38 | |
ETH | <0.01% | $0.005091 | 1,053.7541 | $5.37 | |
ETH | <0.01% | $0.002544 | 2,090 | $5.32 | |
ETH | <0.01% | $187.02 | 0.028 | $5.23 | |
ETH | <0.01% | $0.003775 | 1,381.1656 | $5.21 | |
ETH | <0.01% | $0.041875 | 123.0162 | $5.15 | |
ETH | <0.01% | $0.000355 | 14,441.1955 | $5.13 | |
ETH | <0.01% | $0.00675 | 760 | $5.13 | |
ETH | <0.01% | $0.002345 | 2,183.8608 | $5.12 | |
ETH | <0.01% | $1.98 | 2.5529 | $5.06 | |
ETH | <0.01% | $0.000002 | 2,357,530.1885 | $5.05 | |
ETH | <0.01% | <$0.000001 | 896,994,685,265.6006 | $5.04 | |
ETH | <0.01% | $1,809.03 | 0.00276157 | $5 | |
ETH | <0.01% | $0.02375 | 209 | $4.96 | |
ETH | <0.01% | $0.000183 | 27,039.0774 | $4.96 | |
ETH | <0.01% | $0.017937 | 273.4496 | $4.9 | |
ETH | <0.01% | $0.009874 | 496.3948 | $4.9 | |
ETH | <0.01% | <$0.000001 | 3,170,499,911.4995 | $4.83 | |
ETH | <0.01% | $0.024558 | 190.4406 | $4.68 | |
ETH | <0.01% | $0.229321 | 20.1646 | $4.62 | |
ETH | <0.01% | <$0.000001 | 312,419,910.0687 | $4.61 | |
ETH | <0.01% | $0.000195 | 23,628.2737 | $4.61 | |
ETH | <0.01% | $0.198982 | 22.8783 | $4.55 | |
ETH | <0.01% | $0.001381 | 3,289.4449 | $4.54 | |
ETH | <0.01% | <$0.000001 | 16,493,795.3471 | $4.45 | |
ETH | <0.01% | $0.005294 | 831.8314 | $4.4 | |
ETH | <0.01% | $0.459371 | 9.4526 | $4.34 | |
ETH | <0.01% | $6.51 | 0.659 | $4.29 | |
ETH | <0.01% | $0.004351 | 985.7485 | $4.29 | |
ETH | <0.01% | $1.14 | 3.7463 | $4.27 | |
ETH | <0.01% | <$0.000001 | 3,672,597,326.165 | $4.25 | |
ETH | <0.01% | $0.013907 | 304.2276 | $4.23 | |
ETH | <0.01% | $0.173756 | 23.5156 | $4.09 | |
ETH | <0.01% | $0.059021 | 68.3009 | $4.03 | |
ETH | <0.01% | $0.002764 | 1,453.6421 | $4.02 | |
ETH | <0.01% | $0.018187 | 219.9315 | $4 | |
ETH | <0.01% | $0.000165 | 24,141.5633 | $3.98 | |
ETH | <0.01% | $0.05636 | 70.213 | $3.96 | |
ETH | <0.01% | <$0.000001 | 5,444,599,474.2647 | $3.91 | |
ETH | <0.01% | $0.201459 | 19.3641 | $3.9 | |
ETH | <0.01% | $15,118.89 | 0.0002565 | $3.88 | |
ETH | <0.01% | $0.031399 | 122.9245 | $3.86 | |
ETH | <0.01% | $0.39778 | 9.6495 | $3.84 | |
ETH | <0.01% | $0.032847 | 114.4811 | $3.76 | |
ETH | <0.01% | $0.015419 | 243.2566 | $3.75 | |
ETH | <0.01% | $0.200482 | 18.6074 | $3.73 | |
ETH | <0.01% | $0.001557 | 2,390.0264 | $3.72 | |
ETH | <0.01% | $3.89 | 0.9503 | $3.7 | |
ETH | <0.01% | $0.000853 | 4,280.3833 | $3.65 | |
ETH | <0.01% | $0.003224 | 1,119.8114 | $3.61 | |
ETH | <0.01% | $0.007907 | 453.6907 | $3.59 | |
ETH | <0.01% | $0.20267 | 17.6737 | $3.58 | |
ETH | <0.01% | $372.51 | 0.00956447 | $3.56 | |
ETH | <0.01% | $0.000003 | 1,034,800.0398 | $3.48 | |
ETH | <0.01% | $0.010808 | 320.8317 | $3.47 | |
ETH | <0.01% | $0.000013 | 277,019.5186 | $3.47 | |
ETH | <0.01% | $0.000342 | 10,077.3006 | $3.45 | |
ETH | <0.01% | $0.141415 | 23.4949 | $3.32 | |
ETH | <0.01% | $0.002179 | 1,520 | $3.31 | |
ETH | <0.01% | <$0.000001 | 1,470,551,601.1759 | $3.28 | |
ETH | <0.01% | $57.01 | 0.057 | $3.25 | |
ETH | <0.01% | $0.008935 | 361.8299 | $3.23 | |
ETH | <0.01% | $0.082939 | 38.7322 | $3.21 | |
ETH | <0.01% | $0.005474 | 586.8803 | $3.21 | |
ETH | <0.01% | $0.122732 | 26.1365 | $3.21 | |
ETH | <0.01% | <$0.000001 | 63,592,902.398 | $3.18 | |
ETH | <0.01% | $0.003428 | 923.8012 | $3.17 | |
ETH | <0.01% | $0.030892 | 102.0821 | $3.15 | |
ETH | <0.01% | $0.009893 | 306.2337 | $3.03 | |
ETH | <0.01% | $0.000253 | 11,931.5778 | $3.02 | |
ETH | <0.01% | $0.04731 | 62.9716 | $2.98 | |
ETH | <0.01% | $0.044992 | 65.4136 | $2.94 | |
ETH | <0.01% | <$0.000001 | 5,483,520,059.4306 | $2.93 | |
ETH | <0.01% | $0.001967 | 1,485.7629 | $2.92 | |
ETH | <0.01% | $0.031451 | 92.5281 | $2.91 | |
ETH | <0.01% | $1.67 | 1.7354 | $2.9 | |
ETH | <0.01% | $0.000717 | 3,960.3565 | $2.84 | |
ETH | <0.01% | $0.198523 | 14.1949 | $2.82 | |
ETH | <0.01% | <$0.000001 | 20,579,968.2683 | $2.81 | |
ETH | <0.01% | $0.006741 | 414.4681 | $2.79 | |
ETH | <0.01% | $0.007201 | 384.492 | $2.77 | |
ETH | <0.01% | $1.16 | 2.375 | $2.76 | |
ETH | <0.01% | $0.086182 | 31.6385 | $2.73 | |
ETH | <0.01% | $0.006066 | 449.1476 | $2.72 | |
ETH | <0.01% | $0.000005 | 543,087.3866 | $2.69 | |
ETH | <0.01% | $0.24545 | 10.829 | $2.66 | |
ETH | <0.01% | $0.023745 | 111.6493 | $2.65 | |
ETH | <0.01% | $0.063695 | 41.021 | $2.61 | |
ETH | <0.01% | $0.165176 | 15.6544 | $2.59 | |
ETH | <0.01% | $0.106571 | 23.9963 | $2.56 | |
ETH | <0.01% | $0.118179 | 21.5684 | $2.55 | |
ETH | <0.01% | $0.079988 | 31.4472 | $2.52 | |
ETH | <0.01% | $0.00001 | 259,823.6341 | $2.51 | |
ETH | <0.01% | $0.095102 | 26.267 | $2.5 | |
ETH | <0.01% | $0.007182 | 347.3463 | $2.49 | |
ETH | <0.01% | <$0.000001 | 346,172,868.0011 | $2.47 | |
ETH | <0.01% | $187.79 | 0.0131 | $2.47 | |
ETH | <0.01% | $17.93 | 0.1317 | $2.36 | |
ETH | <0.01% | $0.020761 | 113.4979 | $2.36 | |
ETH | <0.01% | $0.006937 | 333.3507 | $2.31 | |
ETH | <0.01% | $8,672.52 | 0.00026596 | $2.31 | |
ETH | <0.01% | <$0.000001 | 173,481,826,728.9571 | $2.3 | |
ETH | <0.01% | <$0.000001 | 665,000,000.0095 | $2.22 | |
ETH | <0.01% | $0.057893 | 37.6327 | $2.18 | |
ETH | <0.01% | <$0.000001 | 369,540,660.759 | $2.17 | |
ETH | <0.01% | <$0.000001 | 4,810,437.3951 | $2.16 | |
ETH | <0.01% | $0.506093 | 4.2095 | $2.13 | |
ETH | <0.01% | $0.003459 | 614.7666 | $2.13 | |
ETH | <0.01% | $0.008935 | 237.5021 | $2.12 | |
ETH | <0.01% | $0.056821 | 36.6335 | $2.08 | |
ETH | <0.01% | $0.088236 | 23.2402 | $2.05 | |
ETH | <0.01% | $0.002567 | 780.1938 | $2 | |
ETH | <0.01% | $0.007183 | 278.1297 | $2 | |
ETH | <0.01% | $0.10044 | 19.4193 | $1.95 | |
ETH | <0.01% | $0.012437 | 155.1826 | $1.93 | |
ETH | <0.01% | $0.04495 | 42.4868 | $1.91 | |
ETH | <0.01% | $0.000064 | 29,892.7179 | $1.9 | |
ETH | <0.01% | $0.172743 | 10.989 | $1.9 | |
ETH | <0.01% | $0.987081 | 1.9134 | $1.89 | |
ETH | <0.01% | $0.0075 | 246.2212 | $1.85 | |
ETH | <0.01% | $1.27 | 1.4442 | $1.83 | |
ETH | <0.01% | $0.719178 | 2.5183 | $1.81 | |
ETH | <0.01% | $0.000507 | 3,503.9656 | $1.78 | |
ETH | <0.01% | $0.010059 | 171.3729 | $1.72 | |
ETH | <0.01% | $1.02 | 1.6855 | $1.71 | |
ETH | <0.01% | $0.013719 | 123.8757 | $1.7 | |
ETH | <0.01% | $0.086956 | 18.9905 | $1.65 | |
ETH | <0.01% | $0.000934 | 1,764.4839 | $1.65 | |
ETH | <0.01% | $0.000256 | 6,349.1017 | $1.63 | |
ETH | <0.01% | $0.020673 | 77.6959 | $1.61 | |
ETH | <0.01% | $0.000422 | 3,799.4542 | $1.6 | |
ETH | <0.01% | $0.015966 | 100.3057 | $1.6 | |
ETH | <0.01% | $0.091106 | 17.415 | $1.59 | |
ETH | <0.01% | $0.020457 | 77.4588 | $1.58 | |
ETH | <0.01% | $0.032901 | 48.1555 | $1.58 | |
ETH | <0.01% | $0.016543 | 95 | $1.57 | |
ETH | <0.01% | $0.003566 | 439.7888 | $1.57 | |
ETH | <0.01% | $0.084296 | 18.503 | $1.56 | |
ETH | <0.01% | $0.009199 | 169.3281 | $1.56 | |
ETH | <0.01% | $3.13 | 0.4968 | $1.55 | |
ETH | <0.01% | $0.217593 | 7.0754 | $1.54 | |
ETH | <0.01% | <$0.000001 | 153,715,932.7478 | $1.51 | |
ETH | <0.01% | $0.034005 | 44.1712 | $1.5 | |
ETH | <0.01% | $0.233016 | 6.422 | $1.5 | |
ETH | <0.01% | <$0.000001 | 8,740,211.2766 | $1.49 | |
ETH | <0.01% | $0.494221 | 2.9954 | $1.48 | |
ETH | <0.01% | $0.000237 | 6,249.9516 | $1.48 | |
ETH | <0.01% | $0.00031 | 4,763.9687 | $1.48 | |
ETH | <0.01% | $0.002288 | 641.8091 | $1.47 | |
ETH | <0.01% | $0.050791 | 28.9126 | $1.47 | |
ETH | <0.01% | $2.49 | 0.57 | $1.42 | |
ETH | <0.01% | $0.002364 | 589.9224 | $1.39 | |
ETH | <0.01% | $0.000132 | 10,431.7829 | $1.38 | |
ETH | <0.01% | $0.088002 | 15.4565 | $1.36 | |
ETH | <0.01% | $0.004376 | 308.0247 | $1.35 | |
ETH | <0.01% | $28.6 | 0.0468 | $1.34 | |
ETH | <0.01% | $0.034982 | 38.0939 | $1.33 | |
ETH | <0.01% | $0.24922 | 5.2891 | $1.32 | |
ETH | <0.01% | $9.47 | 0.1366 | $1.29 | |
ETH | <0.01% | $0.00003 | 43,139.5 | $1.29 | |
ETH | <0.01% | $0.036769 | 34.675 | $1.27 | |
ETH | <0.01% | $0.000131 | 9,672.1682 | $1.27 | |
ETH | <0.01% | $0.001326 | 954.3701 | $1.27 | |
ETH | <0.01% | $1 | 1.2461 | $1.25 | |
ETH | <0.01% | <$0.000001 | 28,673,298.8527 | $1.24 | |
ETH | <0.01% | $0.000225 | 5,463.0437 | $1.23 | |
ETH | <0.01% | <$0.000001 | 8,046,822.057 | $1.21 | |
ETH | <0.01% | $1.2 | 0.9975 | $1.2 | |
ETH | <0.01% | $0.089864 | 13.3 | $1.2 | |
ETH | <0.01% | $0.059075 | 19.9737 | $1.18 | |
ETH | <0.01% | $0.027101 | 43.5304 | $1.18 | |
ETH | <0.01% | $1,803.68 | 0.00064769 | $1.17 | |
ETH | <0.01% | $0.140207 | 8.2953 | $1.16 | |
ETH | <0.01% | <$0.000001 | 187,380,296.3731 | $1.14 | |
ETH | <0.01% | $0.859628 | 1.3268 | $1.14 | |
ETH | <0.01% | $1.17 | 0.9661 | $1.13 | |
ETH | <0.01% | $0.000521 | 2,165.1504 | $1.13 | |
ETH | <0.01% | $0.010931 | 103.1241 | $1.13 | |
ETH | <0.01% | $0.00074 | 1,486.75 | $1.1 | |
ETH | <0.01% | $0.001027 | 1,051.1057 | $1.08 | |
ETH | <0.01% | $0.030712 | 34.8435 | $1.07 | |
ETH | <0.01% | $0.000185 | 5,715.6364 | $1.05 | |
ETH | <0.01% | $0.000141 | 7,457.0784 | $1.05 | |
ETH | <0.01% | $0.001901 | 546.513 | $1.04 | |
ETH | <0.01% | $1.03 | 1.0071 | $1.04 | |
ETH | <0.01% | $0.000149 | 6,930.3296 | $1.03 | |
ETH | <0.01% | $0.731021 | 1.4095 | $1.03 | |
ETH | <0.01% | $0.000514 | 1,998.9503 | $1.03 | |
ETH | <0.01% | $0.000988 | 994.7317 | $0.9831 | |
ETH | <0.01% | $0.000001 | 716,919.206 | $0.975 | |
ETH | <0.01% | $0.523186 | 1.765 | $0.9234 | |
ETH | <0.01% | $0.010558 | 84.7986 | $0.8952 | |
ETH | <0.01% | <$0.000001 | 14,428,338.4906 | $0.8935 | |
ETH | <0.01% | $0.0002 | 4,423.2571 | $0.8838 | |
ETH | <0.01% | $0.000544 | 1,617.2068 | $0.8798 | |
ETH | <0.01% | $42.08 | 0.0209 | $0.8785 | |
ETH | <0.01% | $0.004305 | 200.2708 | $0.8621 | |
ETH | <0.01% | $0.061376 | 14.0246 | $0.8607 | |
ETH | <0.01% | $0.000561 | 1,520 | $0.853 | |
ETH | <0.01% | <$0.000001 | 207,747,495.7568 | $0.8405 | |
ETH | <0.01% | $0.000281 | 2,971.139 | $0.8361 | |
ETH | <0.01% | <$0.000001 | 13,391,917,412.009 | $0.8299 | |
ETH | <0.01% | $0.011831 | 67.3319 | $0.7966 | |
ETH | <0.01% | $0.013307 | 58.89 | $0.7836 | |
ETH | <0.01% | $0.000362 | 2,093.9975 | $0.757 | |
ETH | <0.01% | $0.000074 | 10,078.8445 | $0.7408 | |
ETH | <0.01% | $0.000372 | 1,962.3521 | $0.7302 | |
ETH | <0.01% | $1.87 | 0.3897 | $0.7286 | |
ETH | <0.01% | $0.02086 | 34.4052 | $0.7177 | |
ETH | <0.01% | $0.399226 | 1.7906 | $0.7148 | |
ETH | <0.01% | <$0.000001 | 4,183,368.0005 | $0.7112 | |
ETH | <0.01% | $0.00333 | 212.0934 | $0.7063 | |
ETH | <0.01% | $1,853.76 | 0.00038 | $0.7044 | |
ETH | <0.01% | $0.038645 | 18.05 | $0.6975 | |
ETH | <0.01% | $0.231927 | 2.9886 | $0.6931 | |
ETH | <0.01% | $0.034982 | 19.2931 | $0.6749 | |
ETH | <0.01% | $0.003537 | 190.6723 | $0.6743 | |
ETH | <0.01% | $0.034566 | 19.4778 | $0.6732 | |
ETH | <0.01% | $0.072157 | 9.3005 | $0.671 | |
ETH | <0.01% | <$0.000001 | 7,851,623,114.3226 | $0.6502 | |
ETH | <0.01% | $0.001828 | 350.7303 | $0.641 | |
ETH | <0.01% | <$0.000001 | 1,019,827,320.2164 | $0.6406 | |
ETH | <0.01% | $0.001341 | 470.5191 | $0.6311 | |
ETH | <0.01% | <$0.000001 | 156,604,808,118.6656 | $0.6198 | |
ETH | <0.01% | $0.000368 | 1,684.3679 | $0.6195 | |
ETH | <0.01% | $0.000834 | 731.085 | $0.6094 | |
ETH | <0.01% | $0.13448 | 4.4737 | $0.6016 | |
ETH | <0.01% | $0.015333 | 38.969 | $0.5975 | |
ETH | <0.01% | $0.013706 | 43.5057 | $0.5962 | |
ETH | <0.01% | $0.000862 | 678.74 | $0.5849 | |
ETH | <0.01% | $0.233016 | 2.4959 | $0.5815 | |
ETH | <0.01% | $3.3 | 0.1713 | $0.5651 | |
ETH | <0.01% | $27.2 | 0.0207 | $0.5636 | |
ETH | <0.01% | $0.0669 | 8.3856 | $0.5609 | |
ETH | <0.01% | $0.422377 | 1.3205 | $0.5577 | |
ETH | <0.01% | $0.05202 | 10.393 | $0.5406 | |
ETH | <0.01% | $2.3 | 0.2321 | $0.5333 | |
ETH | <0.01% | $0.180099 | 2.9115 | $0.5243 | |
ETH | <0.01% | <$0.000001 | 1,995,000 | $0.519 | |
ETH | <0.01% | $0.018342 | 28.1614 | $0.5165 | |
ETH | <0.01% | $0.001262 | 408.1064 | $0.5151 | |
ETH | <0.01% | <$0.000001 | 7,886,565.3678 | $0.5125 | |
ETH | <0.01% | $0.000156 | 3,145.2641 | $0.491 | |
ETH | <0.01% | <$0.000001 | 5,845,877.7725 | $0.4909 | |
ETH | <0.01% | $2.5 | 0.1936 | $0.4841 | |
ETH | <0.01% | $0.391024 | 1.2381 | $0.4841 | |
ETH | <0.01% | $0.01121 | 42.8574 | $0.4804 | |
ETH | <0.01% | $0.031589 | 15.2027 | $0.4802 | |
ETH | <0.01% | $0.004239 | 109.067 | $0.4623 | |
ETH | <0.01% | $0.00631 | 71.3498 | $0.4502 | |
ETH | <0.01% | <$0.000001 | 120,896,937.423 | $0.4486 | |
ETH | <0.01% | $0.098388 | 4.4394 | $0.4367 | |
ETH | <0.01% | $6.16 | 0.07 | $0.4312 | |
ETH | <0.01% | $0.006927 | 61.7213 | $0.4275 | |
ETH | <0.01% | $0.006554 | 65.2171 | $0.4274 | |
ETH | <0.01% | $0.000039 | 10,810.7639 | $0.4227 | |
ETH | <0.01% | $0.000294 | 1,392.6145 | $0.4087 | |
ETH | <0.01% | $0.000014 | 29,212.3808 | $0.3969 | |
ETH | <0.01% | <$0.000001 | 1,522,130,029.7563 | $0.3946 | |
ETH | <0.01% | $0.013016 | 29.5377 | $0.3844 | |
ETH | <0.01% | $0.668178 | 0.567 | $0.3788 | |
ETH | <0.01% | <$0.000001 | 16,320,130.9699 | $0.3779 | |
ETH | <0.01% | $0.025159 | 14.9233 | $0.3754 | |
ETH | <0.01% | $0.006975 | 52.8778 | $0.3688 | |
ETH | <0.01% | $0.012561 | 28.9727 | $0.3639 | |
ETH | <0.01% | $0.01041 | 34.1246 | $0.3552 | |
ETH | <0.01% | $0.000003 | 116,432.1492 | $0.3516 | |
ETH | <0.01% | $0.178686 | 1.9525 | $0.3488 | |
ETH | <0.01% | $0.001896 | 182.6353 | $0.3462 | |
ETH | <0.01% | $0.208393 | 1.6374 | $0.3412 | |
ETH | <0.01% | $0.009185 | 36.9155 | $0.339 | |
ETH | <0.01% | $0.997745 | 0.3365 | $0.3357 | |
ETH | <0.01% | $0.001359 | 237.5 | $0.3227 | |
ETH | <0.01% | $0.004683 | 67.7262 | $0.3171 | |
ETH | <0.01% | $0.000001 | 335,530 | $0.302 | |
ETH | <0.01% | $0.000237 | 1,276.0818 | $0.3018 | |
ETH | <0.01% | $0.000049 | 6,105.1331 | $0.2998 | |
ETH | <0.01% | $0.033685 | 8.8486 | $0.298 | |
ETH | <0.01% | $0.001666 | 178.3882 | $0.2972 | |
ETH | <0.01% | $0.000002 | 126,285.5054 | $0.2911 | |
ETH | <0.01% | <$0.000001 | 460,141,749.3536 | $0.2908 | |
ETH | <0.01% | $0.062079 | 4.5978 | $0.2854 | |
ETH | <0.01% | $0.015824 | 17.5942 | $0.2784 | |
ETH | <0.01% | $0.000557 | 476.2619 | $0.2655 | |
ETH | <0.01% | $0.001052 | 251.1474 | $0.264 | |
ETH | <0.01% | $0.000026 | 9,706.2092 | $0.2566 | |
ETH | <0.01% | $0.183262 | 1.3622 | $0.2496 | |
ETH | <0.01% | $0.000516 | 472.1408 | $0.2435 | |
ETH | <0.01% | $0.002298 | 105.7026 | $0.2428 | |
ETH | <0.01% | $0.000058 | 4,092.1297 | $0.2356 | |
ETH | <0.01% | $1.65 | 0.1425 | $0.2351 | |
ETH | <0.01% | $0.003291 | 70.6841 | $0.2326 | |
ETH | <0.01% | $0.000002 | 133,517.6494 | $0.2256 | |
ETH | <0.01% | $0.002354 | 95.8324 | $0.2255 | |
ETH | <0.01% | $0.047466 | 4.7086 | $0.2234 | |
ETH | <0.01% | $0.000011 | 19,038.8159 | $0.2155 | |
ETH | <0.01% | $0.024152 | 8.7475 | $0.2112 | |
ETH | <0.01% | $0.06991 | 3.0139 | $0.2107 | |
ETH | <0.01% | $0.207156 | 1.0118 | $0.2096 | |
ETH | <0.01% | $0.010044 | 20.6421 | $0.2073 | |
ETH | <0.01% | $0.00011 | 1,867.6784 | $0.2056 | |
ETH | <0.01% | <$0.000001 | 817,000 | $0.2016 | |
ETH | <0.01% | $0.162717 | 1.2344 | $0.2008 | |
ETH | <0.01% | <$0.000001 | 320,895,561.6971 | $0.2005 | |
ETH | <0.01% | $0.002127 | 93.2023 | $0.1982 | |
ETH | <0.01% | $0.000247 | 785.5709 | $0.1941 | |
ETH | <0.01% | $0.013988 | 13.775 | $0.1926 | |
ETH | <0.01% | $0.010036 | 18.9499 | $0.1901 | |
ETH | <0.01% | $0.007404 | 25.175 | $0.1863 | |
ETH | <0.01% | $0.00334 | 55.7722 | $0.1862 | |
ETH | <0.01% | $0.246619 | 0.7507 | $0.1851 | |
ETH | <0.01% | $0.00157 | 117.3412 | $0.1842 | |
ETH | <0.01% | $0.002671 | 68.411 | $0.1826 | |
ETH | <0.01% | $0.001245 | 143.0962 | $0.1781 | |
ETH | <0.01% | $0.000942 | 188.4362 | $0.1774 | |
ETH | <0.01% | $0.0039 | 45.3846 | $0.1769 | |
ETH | <0.01% | $0.000883 | 199.236 | $0.1758 | |
ETH | <0.01% | $0.060703 | 2.8412 | $0.1724 | |
ETH | <0.01% | $0.001053 | 161.5845 | $0.1701 | |
ETH | <0.01% | $0.000024 | 6,795.7715 | $0.1658 | |
ETH | <0.01% | $31.31 | 0.00479807 | $0.1502 | |
ETH | <0.01% | $0.031475 | 4.75 | $0.1495 | |
ETH | <0.01% | $0.980163 | 0.1509 | $0.1479 | |
ETH | <0.01% | $0.000001 | 127,191.3732 | $0.1411 | |
ETH | <0.01% | $4.38 | 0.0322 | $0.1409 | |
ETH | <0.01% | $0.004496 | 31.274 | $0.1406 | |
ETH | <0.01% | $0.00572 | 24.5357 | $0.1403 | |
ETH | <0.01% | $0.503968 | 0.2778 | $0.1399 | |
ETH | <0.01% | $0.442616 | 0.2864 | $0.1267 | |
ETH | <0.01% | $0.000268 | 444.4619 | $0.119 | |
ETH | <0.01% | $0.002619 | 44.7206 | $0.1171 | |
ETH | <0.01% | $0.001197 | 96.3086 | $0.1153 | |
ETH | <0.01% | <$0.000001 | 2,524,200.5976 | $0.1139 | |
ETH | <0.01% | <$0.000001 | 2,375,000 | $0.113 | |
ETH | <0.01% | $0.002671 | 40.4275 | $0.1079 | |
ETH | <0.01% | $0.006499 | 16.5923 | $0.1078 | |
ETH | <0.01% | $0.00056 | 191.1343 | $0.1069 | |
ETH | <0.01% | $0.000526 | 198.1675 | $0.1042 | |
ETH | <0.01% | $0.000116 | 893.836 | $0.1033 | |
ETH | <0.01% | $0.0002 | 512.2618 | $0.1024 | |
ETH | <0.01% | $0.317444 | 0.3222 | $0.1022 | |
ETH | <0.01% | $0.0004 | 252.9596 | $0.1011 | |
ETH | <0.01% | $1.01 | 0.1 | $0.1004 | |
BSC | 13.35% | $1.86 | 7,477.1143 | $13,937.75 | |
BSC | 0.34% | $1 | 359.2019 | $359.2 | |
BSC | 0.32% | $0.418246 | 795.7677 | $332.83 | |
BSC | 0.27% | $1 | 280.9665 | $281.08 | |
BSC | 0.26% | $674.38 | 0.4069 | $274.41 | |
BSC | 0.26% | $612.83 | 0.4432 | $271.62 | |
BSC | 0.22% | $14.97 | 15.5643 | $232.93 | |
BSC | 0.20% | $0.088237 | 2,383.7727 | $210.34 | |
BSC | 0.20% | $0.001081 | 194,509.0132 | $210.2 | |
BSC | 0.18% | $1,802.29 | 0.1071 | $192.96 | |
BSC | 0.15% | $152.89 | 1.0405 | $159.08 | |
BSC | 0.15% | $2.03 | 77.5487 | $157.42 | |
BSC | 0.14% | $165.45 | 0.8817 | $145.88 | |
BSC | 0.13% | $0.000069 | 2,019,817.5018 | $139.67 | |
BSC | 0.13% | $9.56 | 14.3034 | $136.74 | |
BSC | 0.12% | $0.245544 | 524.992 | $128.91 | |
BSC | 0.12% | $0.222397 | 571.746 | $127.15 | |
BSC | 0.12% | $1.3 | 92.2091 | $120.12 | |
BSC | 0.11% | $2.27 | 52.2511 | $118.51 | |
BSC | 0.10% | $22.86 | 4.6588 | $106.5 | |
BSC | 0.09% | $0.999964 | 92.5106 | $92.51 | |
BSC | 0.08% | $0.030949 | 2,736.1294 | $84.68 | |
BSC | 0.07% | $3.49 | 21.8076 | $76.11 | |
BSC | 0.07% | $0.213398 | 348.5195 | $74.37 | |
BSC | 0.07% | $3.12 | 23.1255 | $72.15 | |
BSC | 0.07% | $2.74 | 25.7122 | $70.57 | |
BSC | 0.06% | $0.183004 | 365.9502 | $66.97 | |
BSC | 0.06% | $0.825932 | 78.4722 | $64.81 | |
BSC | 0.06% | $6.04 | 10.3609 | $62.62 | |
BSC | 0.06% | $0.013708 | 4,520.233 | $61.96 | |
BSC | 0.06% | $0.194225 | 307.4019 | $59.71 | |
BSC | 0.05% | $0.31351 | 179.0915 | $56.15 | |
BSC | 0.05% | $0.519707 | 107.8595 | $56.06 | |
BSC | 0.05% | $0.000324 | 158,693.447 | $51.47 | |
BSC | 0.05% | $2.89 | 16.6666 | $48.17 | |
BSC | 0.05% | $4.38 | 10.8238 | $47.42 | |
BSC | 0.04% | $0.019678 | 2,251.6044 | $44.31 | |
BSC | 0.04% | $2.48 | 17.4592 | $43.34 | |
BSC | 0.04% | $0.000037 | 1,091,885.2097 | $39.96 | |
BSC | 0.04% | $0.211705 | 187.4891 | $39.69 | |
BSC | 0.04% | $0.071258 | 547.6149 | $39.02 | |
BSC | 0.03% | $0.920338 | 38.4421 | $35.38 | |
BSC | 0.03% | <$0.000001 | 24,029,814,184.2528 | $35.35 | |
BSC | 0.03% | $611.62 | 0.0544 | $33.25 | |
BSC | 0.03% | $0.998876 | 29.748 | $29.71 | |
BSC | 0.03% | $0.015767 | 1,778.9392 | $28.05 | |
BSC | 0.03% | $0.029344 | 950.9913 | $27.91 | |
BSC | 0.03% | $0.18886 | 147.1022 | $27.78 | |
BSC | 0.03% | $0.01276 | 2,145.1977 | $27.37 | |
BSC | 0.02% | $0.514379 | 48.9887 | $25.2 | |
BSC | 0.02% | $0.569731 | 39.8357 | $22.7 | |
BSC | 0.02% | $0.703248 | 31.3867 | $22.07 | |
BSC | 0.02% | $0.561522 | 38.9519 | $21.87 | |
BSC | 0.02% | $0.000139 | 156,516.617 | $21.77 | |
BSC | 0.02% | <$0.000001 | 133,590,845.6348 | $18.72 | |
BSC | 0.02% | $0.349623 | 53.3117 | $18.64 | |
BSC | 0.02% | $1 | 17.5362 | $17.54 | |
BSC | 0.01% | $0.000001 | 24,204,838.5786 | $15.46 | |
BSC | 0.01% | $0.135004 | 107.0457 | $14.45 | |
BSC | 0.01% | $93,661.73 | 0.0001514 | $14.18 | |
BSC | 0.01% | $0.668281 | 20.4349 | $13.66 | |
BSC | 0.01% | $0.000016 | 802,450.5296 | $12.88 | |
BSC | 0.01% | $0.05636 | 218.1091 | $12.29 | |
BSC | 0.01% | $0.970781 | 11.1172 | $10.79 | |
BSC | 0.01% | $0.008223 | 1,306.8005 | $10.75 | |
BSC | <0.01% | $0.026175 | 392.5492 | $10.27 | |
BSC | <0.01% | $0.004305 | 2,345.7977 | $10.1 | |
BSC | <0.01% | $0.212213 | 45.1071 | $9.57 | |
BSC | <0.01% | $0.091403 | 102.1039 | $9.33 | |
BSC | <0.01% | $0.000014 | 681,549.4736 | $9.32 | |
BSC | <0.01% | $0.344575 | 26.6253 | $9.17 | |
BSC | <0.01% | $0.016671 | 506.1592 | $8.44 | |
BSC | <0.01% | $4.13 | 1.8912 | $7.82 | |
BSC | <0.01% | $0.000014 | 541,500 | $7.54 | |
BSC | <0.01% | $0.000149 | 50,427.6911 | $7.54 | |
BSC | <0.01% | $0.074798 | 97.4654 | $7.29 | |
BSC | <0.01% | $0.000007 | 967,946.3689 | $7.13 | |
BSC | <0.01% | $0.002927 | 2,434.7415 | $7.13 | |
BSC | <0.01% | $0.000177 | 39,978.5568 | $7.09 | |
BSC | <0.01% | $7.76 | 0.8738 | $6.78 | |
BSC | <0.01% | $0.255404 | 26.2219 | $6.7 | |
BSC | <0.01% | $1,800.51 | 0.00364233 | $6.56 | |
BSC | <0.01% | $0.003091 | 1,998.5515 | $6.18 | |
BSC | <0.01% | $0.272934 | 22.1617 | $6.05 | |
BSC | <0.01% | <$0.000001 | 454,341,179.0794 | $6.05 | |
BSC | <0.01% | <$0.000001 | 17,378,518,317.666 | $5.57 | |
BSC | <0.01% | $2.54 | 2.068 | $5.25 | |
BSC | <0.01% | $0.011694 | 441.723 | $5.17 | |
BSC | <0.01% | $0.209529 | 23.4535 | $4.91 | |
BSC | <0.01% | $0.000001 | 3,548,299.286 | $4.51 | |
BSC | <0.01% | <$0.000001 | 67,891,494.8348 | $4.41 | |
BSC | <0.01% | $0.000053 | 81,327.0775 | $4.31 | |
BSC | <0.01% | $0.488971 | 8.487 | $4.15 | |
BSC | <0.01% | $1.34 | 2.9988 | $4.02 | |
BSC | <0.01% | $0.197573 | 19.4961 | $3.85 | |
BSC | <0.01% | $5.54 | 0.6947 | $3.85 | |
BSC | <0.01% | $0.006202 | 564.9885 | $3.5 | |
BSC | <0.01% | $0.015824 | 216.2187 | $3.42 | |
BSC | <0.01% | $0.205895 | 16.319 | $3.36 | |
BSC | <0.01% | $0.03582 | 92.1916 | $3.3 | |
BSC | <0.01% | $0.272213 | 11.1019 | $3.02 | |
BSC | <0.01% | $2.93 | 0.9751 | $2.86 | |
BSC | <0.01% | $0.004402 | 634.5905 | $2.79 | |
BSC | <0.01% | $0.601507 | 4.6221 | $2.78 | |
BSC | <0.01% | $0.026171 | 104.4102 | $2.73 | |
BSC | <0.01% | $668.91 | 0.00389151 | $2.6 | |
BSC | <0.01% | $84.08 | 0.0302 | $2.54 | |
BSC | <0.01% | <$0.000001 | 6,698,304,301.7647 | $2.45 | |
BSC | <0.01% | $43.42 | 0.054 | $2.35 | |
BSC | <0.01% | $0.004145 | 563.17 | $2.33 | |
BSC | <0.01% | $0.020137 | 115.076 | $2.32 | |
BSC | <0.01% | $0.998777 | 2.3039 | $2.3 | |
BSC | <0.01% | $0.240159 | 9.5195 | $2.29 | |
BSC | <0.01% | $0.058516 | 36.3046 | $2.12 | |
BSC | <0.01% | $0.014896 | 139.0895 | $2.07 | |
BSC | <0.01% | $33.36 | 0.0575 | $1.92 | |
BSC | <0.01% | $0.459371 | 4.1694 | $1.92 | |
BSC | <0.01% | $0.028377 | 66.4838 | $1.89 | |
BSC | <0.01% | $0.170149 | 9.2071 | $1.57 | |
BSC | <0.01% | $0.075986 | 19.9054 | $1.51 | |
BSC | <0.01% | $0.000558 | 2,672.7315 | $1.49 | |
BSC | <0.01% | $0.523186 | 2.8178 | $1.47 | |
BSC | <0.01% | $1,507.36 | 0.00095 | $1.43 | |
BSC | <0.01% | $0.106044 | 13.4788 | $1.43 | |
BSC | <0.01% | $0.666132 | 2.1311 | $1.42 | |
BSC | <0.01% | $0.032638 | 41.7447 | $1.36 | |
BSC | <0.01% | $0.000156 | 8,617.2722 | $1.35 | |
BSC | <0.01% | $0.060026 | 21.9416 | $1.32 | |
BSC | <0.01% | $0.000342 | 3,800 | $1.3 | |
BSC | <0.01% | $0.023112 | 56.1376 | $1.3 | |
BSC | <0.01% | $0.07787 | 16.2244 | $1.26 | |
BSC | <0.01% | $0.087546 | 13.4606 | $1.18 | |
BSC | <0.01% | $0.018745 | 62.6066 | $1.17 | |
BSC | <0.01% | $0.001612 | 722 | $1.16 | |
BSC | <0.01% | $1.52 | 0.76 | $1.16 | |
BSC | <0.01% | $0.000034 | 33,066.8985 | $1.14 | |
BSC | <0.01% | $0.142414 | 7.8459 | $1.12 | |
BSC | <0.01% | $0.041759 | 24.2282 | $1.01 | |
BSC | <0.01% | $0.007459 | 135.1494 | $1.01 | |
BSC | <0.01% | $0.000308 | 3,263.4081 | $1.01 | |
BSC | <0.01% | $0.007733 | 129.2897 | $0.9997 | |
BSC | <0.01% | $0.002072 | 477.5062 | $0.9894 | |
BSC | <0.01% | $0.00787 | 125.2008 | $0.9853 | |
BSC | <0.01% | $0.000364 | 2,482.7103 | $0.9028 | |
BSC | <0.01% | $0.014726 | 58.8153 | $0.8661 | |
BSC | <0.01% | $0.000008 | 110,411.9854 | $0.8567 | |
BSC | <0.01% | $2.99 | 0.2847 | $0.8512 | |
BSC | <0.01% | $0.008892 | 95 | $0.8447 | |
BSC | <0.01% | $0.024695 | 33.6779 | $0.8316 | |
BSC | <0.01% | $0.140318 | 5.8038 | $0.8143 | |
BSC | <0.01% | $0.001706 | 474.1841 | $0.8088 | |
BSC | <0.01% | $0.126917 | 6.0705 | $0.7704 | |
BSC | <0.01% | $0.121287 | 6.2147 | $0.7537 | |
BSC | <0.01% | $0.021947 | 33.7761 | $0.7412 | |
BSC | <0.01% | $0.04492 | 15.9829 | $0.7179 | |
BSC | <0.01% | $0.208393 | 3.1229 | $0.6507 | |
BSC | <0.01% | $0.000014 | 45,802.9013 | $0.6288 | |
BSC | <0.01% | $0.000641 | 956.0917 | $0.613 | |
BSC | <0.01% | $0.090151 | 6.7957 | $0.6126 | |
BSC | <0.01% | $0.953946 | 0.5988 | $0.5712 | |
BSC | <0.01% | $0.999553 | 0.5306 | $0.5303 | |
BSC | <0.01% | $0.188182 | 2.7459 | $0.5167 | |
BSC | <0.01% | $0.000368 | 1,404.594 | $0.5163 | |
BSC | <0.01% | $0.422275 | 1.1759 | $0.4965 | |
BSC | <0.01% | <$0.000001 | 33,246,827.4175 | $0.478 | |
BSC | <0.01% | $0.01189 | 37.2404 | $0.4428 | |
BSC | <0.01% | $0.009855 | 43.9845 | $0.4334 | |
BSC | <0.01% | $0.092439 | 4.5574 | $0.4212 | |
BSC | <0.01% | $0.003749 | 109.2326 | $0.4094 | |
BSC | <0.01% | $0.000092 | 4,369.5744 | $0.3999 | |
BSC | <0.01% | $0.035701 | 11.1903 | $0.3994 | |
BSC | <0.01% | $0.04731 | 8.4189 | $0.3982 | |
BSC | <0.01% | $0.014416 | 27.3635 | $0.3944 | |
BSC | <0.01% | $0.026835 | 14.3075 | $0.3839 | |
BSC | <0.01% | $40.88 | 0.00888536 | $0.3632 | |
BSC | <0.01% | $2.41 | 0.1453 | $0.3506 | |
BSC | <0.01% | $0.04334 | 7.7712 | $0.3368 | |
BSC | <0.01% | $0.059075 | 5.1615 | $0.3049 | |
BSC | <0.01% | $0.006937 | 43.9391 | $0.3048 | |
BSC | <0.01% | $0.000121 | 2,483.4582 | $0.3007 | |
BSC | <0.01% | $0.007978 | 35.881 | $0.2862 | |
BSC | <0.01% | $0.009689 | 28.6984 | $0.278 | |
BSC | <0.01% | <$0.000001 | 1,063,205,628.9065 | $0.2598 | |
BSC | <0.01% | $2.71 | 0.0958 | $0.2595 | |
BSC | <0.01% | $0.047496 | 5.3474 | $0.2539 | |
BSC | <0.01% | $0.06987 | 3.5942 | $0.2511 | |
BSC | <0.01% | $0.00314 | 79.2493 | $0.2488 | |
BSC | <0.01% | <$0.000001 | 48,826,016.3561 | $0.246 | |
BSC | <0.01% | $0.000125 | 1,960.2212 | $0.2448 | |
BSC | <0.01% | <$0.000001 | 2,396,977.1664 | $0.2342 | |
BSC | <0.01% | $0.000022 | 10,003.7888 | $0.2219 | |
BSC | <0.01% | $0.074904 | 2.8129 | $0.2106 | |
BSC | <0.01% | $1.36 | 0.1529 | $0.2084 | |
BSC | <0.01% | $0.034872 | 5.3594 | $0.1868 | |
BSC | <0.01% | $0.023191 | 5.9105 | $0.137 | |
BSC | <0.01% | $0.000002 | 88,285.4161 | $0.1368 | |
BSC | <0.01% | $0.007045 | 19.3137 | $0.136 | |
BSC | <0.01% | $0.000562 | 237.0901 | $0.1332 | |
BSC | <0.01% | $0.061376 | 2.1421 | $0.1314 | |
BSC | <0.01% | $0.082018 | 1.5392 | $0.1262 | |
BSC | <0.01% | $0.058379 | 2.1479 | $0.1253 | |
BSC | <0.01% | $0.123612 | 0.9955 | $0.123 | |
BSC | <0.01% | $0.00001 | 12,141.357 | $0.1199 | |
BSC | <0.01% | $0.058035 | 2.011 | $0.1167 | |
BSC | <0.01% | $0.025927 | 4.0755 | $0.1056 | |
BSC | <0.01% | $0.000955 | 107.9817 | $0.103 | |
BSC | <0.01% | $1 | 0.1004 | $0.1007 | |
POL | 0.35% | $0.999905 | 364.4561 | $364.42 | |
POL | 0.26% | $4.65 | 58.8984 | $273.88 | |
POL | 0.21% | $0.999905 | 222.8166 | $222.8 | |
POL | 0.21% | $0.22356 | 973.1378 | $217.55 | |
POL | 0.20% | $1 | 209.9225 | $209.92 | |
POL | 0.19% | $93,661 | 0.00215012 | $201.38 | |
POL | 0.14% | $1,802.06 | 0.0837 | $150.78 | |
POL | 0.11% | $0.298811 | 399.6594 | $119.42 | |
POL | 0.10% | $0.012344 | 8,494.8205 | $104.86 | |
POL | 0.07% | $1 | 73.4009 | $73.4 | |
POL | 0.07% | $0.006265 | 11,371.07 | $71.24 | |
POL | 0.06% | $14.96 | 3.8693 | $57.88 | |
POL | 0.05% | $0.256177 | 218.6827 | $56.02 | |
POL | 0.02% | $165.39 | 0.151 | $24.97 | |
POL | 0.02% | $0.09135 | 248.1169 | $22.67 | |
POL | 0.02% | $0.238032 | 85.8818 | $20.44 | |
POL | 0.02% | $1.14 | 17.1406 | $19.54 | |
POL | 0.02% | $1.14 | 17.1406 | $19.54 | |
POL | 0.01% | $0.998691 | 14.385 | $14.37 | |
POL | 0.01% | $1.12 | 11.62 | $13.01 | |
POL | 0.01% | $0.009523 | 1,130.9296 | $10.77 | |
POL | <0.01% | $0.22914 | 39.07 | $8.95 | |
POL | <0.01% | $0.052953 | 143.45 | $7.6 | |
POL | <0.01% | $0.682633 | 10.6769 | $7.29 | |
POL | <0.01% | $0.198141 | 33.8122 | $6.7 | |
POL | <0.01% | $0.006103 | 1,012.3509 | $6.18 | |
POL | <0.01% | $0.024897 | 210.7231 | $5.25 | |
POL | <0.01% | $6.04 | 0.8454 | $5.11 | |
POL | <0.01% | $0.313064 | 13.6378 | $4.27 | |
POL | <0.01% | $0.217569 | 16.834 | $3.66 | |
POL | <0.01% | $1.31 | 2.6644 | $3.49 | |
POL | <0.01% | $0.020665 | 152.1933 | $3.15 | |
POL | <0.01% | $0.062428 | 48.4337 | $3.02 | |
POL | <0.01% | $0.222259 | 13.314 | $2.96 | |
POL | <0.01% | $0.336796 | 7.9775 | $2.69 | |
POL | <0.01% | $0.071725 | 29.2117 | $2.1 | |
POL | <0.01% | $0.810313 | 2.5327 | $2.05 | |
POL | <0.01% | <$0.000001 | 289,929,866.0337 | $1.68 | |
POL | <0.01% | $0.562511 | 2.5033 | $1.41 | |
POL | <0.01% | $0.999673 | 1.3225 | $1.32 | |
POL | <0.01% | $0.282563 | 4.2022 | $1.19 | |
POL | <0.01% | $0.015822 | 74.2383 | $1.17 | |
POL | <0.01% | $0.363332 | 3.1251 | $1.14 | |
POL | <0.01% | $0.253929 | 4.3429 | $1.1 | |
POL | <0.01% | $1,504.62 | 0.00071202 | $1.07 | |
POL | <0.01% | $0.594088 | 1.6606 | $0.9865 | |
POL | <0.01% | $0.282308 | 3.4857 | $0.984 | |
POL | <0.01% | $0.202565 | 4.4424 | $0.8998 | |
POL | <0.01% | $0.057814 | 11.438 | $0.6612 | |
POL | <0.01% | $0.980667 | 0.6449 | $0.6324 | |
POL | <0.01% | $43.4 | 0.0095 | $0.4123 | |
POL | <0.01% | $1.56 | 0.2601 | $0.4057 | |
POL | <0.01% | $0.000195 | 1,463.8616 | $0.2854 | |
POL | <0.01% | $0.058279 | 4.1625 | $0.2425 | |
POL | <0.01% | $0.170653 | 1.3521 | $0.2307 | |
POL | <0.01% | $0.003597 | 49.2916 | $0.1772 | |
POL | <0.01% | $0.27362 | 0.559 | $0.1529 | |
POL | <0.01% | $0.004399 | 33.25 | $0.1462 | |
POL | <0.01% | $0.73533 | 0.19 | $0.1397 | |
POL | <0.01% | $0.001873 | 61.5599 | $0.1152 | |
POL | <0.01% | $0.000002 | 46,750 | $0.1098 | |
POL | <0.01% | $1.14 | 0.091 | $0.1037 | |
ARB | 0.30% | $1,804.4 | 0.1743 | $314.51 | |
ARB | 0.16% | $0.999993 | 167.5257 | $167.52 | |
ARB | 0.12% | $1,805.92 | 0.0681 | $122.91 | |
ARB | 0.08% | $15.11 | 5.2338 | $79.08 | |
ARB | 0.06% | $0.331224 | 199.6193 | $66.12 | |
ARB | 0.04% | $93,703 | 0.00046769 | $43.82 | |
ARB | 0.04% | $2,163.93 | 0.0198 | $42.77 | |
ARB | 0.02% | $0.061498 | 368.4662 | $22.66 | |
ARB | 0.01% | $2,034.36 | 0.00609603 | $12.4 | |
ARB | <0.01% | $2.71 | 2.7979 | $7.58 | |
ARB | <0.01% | $0.684538 | 9.8218 | $6.72 | |
ARB | <0.01% | $1.14 | 5.7 | $6.5 | |
ARB | <0.01% | $6.06 | 1.0568 | $6.4 | |
ARB | <0.01% | $0.102889 | 57 | $5.86 | |
ARB | <0.01% | $0.812005 | 6.7044 | $5.44 | |
ARB | <0.01% | $43.46 | 0.0659 | $2.86 | |
ARB | <0.01% | $165.68 | 0.0143 | $2.37 | |
ARB | <0.01% | $1 | 2.128 | $2.13 | |
ARB | <0.01% | $0.674403 | 2.375 | $1.6 | |
ARB | <0.01% | $0.091476 | 11.6338 | $1.06 | |
ARB | <0.01% | $0.999937 | 0.9671 | $0.967 | |
ARB | <0.01% | $1.14 | 0.7978 | $0.9095 | |
ARB | <0.01% | $3.49 | 0.2156 | $0.7523 | |
ARB | <0.01% | $0.025925 | 17.0813 | $0.4428 | |
ARB | <0.01% | $1,886.79 | 0.00022163 | $0.4181 | |
ARB | <0.01% | $0.082266 | 4.2003 | $0.3455 | |
ARB | <0.01% | $0.000669 | 252.08 | $0.1686 | |
ARB | <0.01% | $0.2213 | 0.6418 | $0.142 | |
ARB | <0.01% | $15 | 0.00776399 | $0.1164 | |
BASE | 0.32% | $1,803.3 | 0.1831 | $330.15 | |
BASE | 0.10% | $93,789 | 0.00110814 | $103.93 | |
BASE | 0.10% | $0.022198 | 4,669.1313 | $103.65 | |
BASE | 0.07% | $0.000385 | 191,785.0189 | $73.92 | |
BASE | 0.06% | $0.048345 | 1,366.4374 | $66.06 | |
BASE | 0.02% | $2.77 | 9.1032 | $25.22 | |
BASE | 0.02% | $0.003308 | 7,617.5217 | $25.19 | |
BASE | 0.02% | $0.055893 | 321.1 | $17.95 | |
BASE | 0.01% | $0.00611 | 2,534.9168 | $15.49 | |
BASE | 0.01% | $0.999971 | 12.9893 | $12.99 | |
BASE | 0.01% | $0.176148 | 68.6334 | $12.09 | |
BASE | 0.01% | $0.501571 | 21.518 | $10.79 | |
BASE | <0.01% | $0.001093 | 7,600 | $8.3 | |
BASE | <0.01% | $0.000149 | 50,427.6911 | $7.54 | |
BASE | <0.01% | $0.000156 | 43,786.868 | $6.85 | |
BASE | <0.01% | $0.000579 | 7,568.1002 | $4.38 | |
BASE | <0.01% | $1,978.16 | 0.00196761 | $3.89 | |
BASE | <0.01% | $0.56336 | 6.8305 | $3.85 | |
BASE | <0.01% | $0.126825 | 28.7479 | $3.65 | |
BASE | <0.01% | $0.000165 | 15,527.1669 | $2.56 | |
BASE | <0.01% | $0.001326 | 1,732.287 | $2.3 | |
BASE | <0.01% | $0.002333 | 950 | $2.22 | |
BASE | <0.01% | $0.003939 | 516.2911 | $2.03 | |
BASE | <0.01% | $0.00418 | 475 | $1.99 | |
BASE | <0.01% | $1,805.91 | 0.00099772 | $1.8 | |
BASE | <0.01% | $0.003597 | 405.5564 | $1.46 | |
BASE | <0.01% | $0.006613 | 199.5384 | $1.32 | |
BASE | <0.01% | $0.000002 | 743,000 | $1.21 | |
BASE | <0.01% | $0.001128 | 1,032.6493 | $1.16 | |
BASE | <0.01% | $0.000334 | 3,314 | $1.11 | |
BASE | <0.01% | $0.000005 | 199,541.8812 | $1.08 | |
BASE | <0.01% | $0.245588 | 4.2625 | $1.05 | |
BASE | <0.01% | $0.016444 | 62.7 | $1.03 | |
BASE | <0.01% | $0.000016 | 60,727.2122 | $0.9904 | |
BASE | <0.01% | $0.000013 | 76,007.6573 | $0.9592 | |
BASE | <0.01% | $0.062966 | 12.445 | $0.7836 | |
BASE | <0.01% | $0.000001 | 939,161.9579 | $0.5505 | |
BASE | <0.01% | $0.000016 | 28,840.9268 | $0.4513 | |
BASE | <0.01% | $0.208725 | 2.1306 | $0.4447 | |
BASE | <0.01% | $0.000049 | 8,266.0931 | $0.4069 | |
BASE | <0.01% | $0.235761 | 1.2768 | $0.301 | |
BASE | <0.01% | $2,021.83 | 0.0001349 | $0.2727 | |
BASE | <0.01% | $0.003483 | 75.847 | $0.2641 | |
BASE | <0.01% | $0.000004 | 64,652.0624 | $0.2588 | |
BASE | <0.01% | $0.00047 | 522.0314 | $0.2451 | |
BASE | <0.01% | $0.000044 | 4,750 | $0.2079 | |
BASE | <0.01% | $1 | 0.2011 | $0.201 | |
BASE | <0.01% | $0.001036 | 189.5798 | $0.1963 | |
BASE | <0.01% | $0.00051 | 312.6463 | $0.1595 | |
BASE | <0.01% | $0.783508 | 0.186 | $0.1457 | |
BASE | <0.01% | $2,165.01 | 0.00006033 | $0.1306 | |
BASE | <0.01% | $0.000332 | 364.9957 | $0.1211 | |
OP | 0.13% | $93,829 | 0.00149961 | $140.71 | |
OP | 0.07% | $1,804.21 | 0.0422 | $76.14 | |
OP | 0.07% | $0.999905 | 74.9045 | $74.9 | |
OP | <0.01% | $0.759734 | 9.7157 | $7.38 | |
OP | <0.01% | $1,805.54 | 0.00059922 | $1.08 | |
OP | <0.01% | $0.999905 | 0.8739 | $0.8738 | |
OP | <0.01% | $1 | 0.7577 | $0.7576 | |
OP | <0.01% | $0.869518 | 0.8587 | $0.7466 | |
OP | <0.01% | $10.99 | 0.0243 | $0.2666 | |
ZKSYNC | <0.01% | $1,804.98 | 0.00001425 | $0.025721 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.