More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
134713987 | 3 hrs ago | 0.000006119770348 ETH | ||||
134704176 | 9 hrs ago | 0.000003469539005 ETH | ||||
134702732 | 10 hrs ago | 0.000000838226468 ETH | ||||
134695672 | 14 hrs ago | 0.000008554243765 ETH | ||||
134662165 | 32 hrs ago | 0.000000030681812 ETH | ||||
134648181 | 40 hrs ago | 0.000023286396202 ETH | ||||
134646821 | 41 hrs ago | 0.000000384413037 ETH | ||||
134612302 | 2 days ago | 0.000010404911435 ETH | ||||
134589703 | 3 days ago | 0.000000307147425 ETH | ||||
134584710 | 3 days ago | 0.000000020115464 ETH | ||||
134584524 | 3 days ago | 0.00000330800556 ETH | ||||
134583116 | 3 days ago | 0.000000212537874 ETH | ||||
134579094 | 3 days ago | 0.00000000007916 ETH | ||||
134566264 | 3 days ago | 0.000000789559897 ETH | ||||
134557648 | 3 days ago | 0.000181532921113 ETH | ||||
134550577 | 3 days ago | 0.000000009267898 ETH | ||||
134547063 | 4 days ago | 0.000000133652932 ETH | ||||
134527995 | 4 days ago | 0.000893222998633 ETH | ||||
134524511 | 4 days ago | 0.000315350950636 ETH | ||||
134518077 | 4 days ago | 0.000275644611489 ETH | ||||
134511444 | 4 days ago | 0.000000294270582 ETH | ||||
134508730 | 4 days ago | 0.00000458319507 ETH | ||||
134508665 | 4 days ago | 0.000004167593824 ETH | ||||
134508424 | 4 days ago | 0.000003099462382 ETH | ||||
134501417 | 5 days ago | 0.000286024767811 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 |
---|---|---|---|---|---|
BSC | 75.37% | $0.009053 | 1,048,942.3149 | $9,495.55 | |
BSC | 5.00% | $0.144765 | 4,355.0223 | $630.45 | |
BSC | 0.51% | $1.17 | 54.7896 | $64.1 | |
BSC | 0.36% | <$0.000001 | 715,261,590.4894 | $45.27 | |
BSC | 0.05% | $1.3 | 4.96 | $6.46 | |
BSC | 0.03% | $0.291995 | 12.9996 | $3.8 | |
BSC | 0.03% | $137.98 | 0.0238 | $3.28 | |
BSC | 0.02% | $0.159372 | 19.7332 | $3.14 | |
BSC | 0.02% | $3.16 | 0.9676 | $3.06 | |
BSC | 0.02% | $0.023527 | 125.5441 | $2.95 | |
BSC | 0.02% | $0.014986 | 189.6418 | $2.84 | |
BSC | 0.02% | $0.041788 | 64.6295 | $2.7 | |
BSC | 0.02% | $0.042522 | 63.3026 | $2.69 | |
BSC | 0.02% | <$0.000001 | 598,953,315.6975 | $2.64 | |
BSC | 0.02% | $0.002012 | 1,260.7055 | $2.54 | |
BSC | 0.02% | $1.66 | 1.512 | $2.51 | |
BSC | 0.02% | $0.007938 | 312.2562 | $2.48 | |
BSC | 0.02% | $14.19 | 0.1682 | $2.39 | |
BSC | 0.02% | $0.122354 | 17.8661 | $2.19 | |
BSC | 0.02% | $0.000007 | 297,355.734 | $2.17 | |
BSC | 0.02% | $3 | 0.7221 | $2.17 | |
BSC | 0.02% | $5.25 | 0.4116 | $2.16 | |
BSC | 0.02% | $0.021205 | 101.9582 | $2.16 | |
BSC | 0.02% | $19.26 | 0.1109 | $2.14 | |
BSC | 0.02% | $0.19001 | 11.1574 | $2.12 | |
BSC | 0.02% | $0.004047 | 518.5232 | $2.1 | |
BSC | 0.02% | $0.020181 | 95.5762 | $1.93 | |
BSC | 0.01% | $2.1 | 0.8905 | $1.87 | |
BSC | 0.01% | $592.83 | 0.00300022 | $1.78 | |
BSC | 0.01% | $0.03787 | 46.5285 | $1.76 | |
BSC | 0.01% | $12.78 | 0.1305 | $1.67 | |
BSC | 0.01% | $0.005252 | 317.533 | $1.67 | |
BSC | 0.01% | $0.05673 | 29.0158 | $1.65 | |
BSC | 0.01% | $40.88 | 0.0377 | $1.54 | |
BSC | 0.01% | $0.273135 | 5.5724 | $1.52 | |
BSC | 0.01% | $0.016022 | 94.4686 | $1.51 | |
BSC | 0.01% | $0.011018 | 132.4172 | $1.46 | |
BSC | 0.01% | $0.003355 | 423.6534 | $1.42 | |
BSC | 0.01% | $0.626451 | 2.2681 | $1.42 | |
BSC | 0.01% | $0.001123 | 1,262.2219 | $1.42 | |
BSC | 0.01% | $0.004191 | 324.1469 | $1.36 | |
BSC | 0.01% | $0.000132 | 10,101.0936 | $1.33 | |
BSC | 0.01% | $0.013952 | 95.1157 | $1.33 | |
BSC | 0.01% | $0.009262 | 142.4026 | $1.32 | |
BSC | 0.01% | $0.997245 | 1.3209 | $1.32 | |
BSC | 0.01% | $0.466262 | 2.8018 | $1.31 | |
BSC | 0.01% | $0.109803 | 11.8153 | $1.3 | |
BSC | <0.01% | $0.239163 | 5.1395 | $1.23 | |
BSC | <0.01% | $2.16 | 0.5563 | $1.2 | |
BSC | <0.01% | <$0.000001 | 15,174,010.6657 | $1.19 | |
BSC | <0.01% | $0.001046 | 1,124.1039 | $1.18 | |
BSC | <0.01% | $0.050632 | 23.1892 | $1.17 | |
BSC | <0.01% | $5.1 | 0.2292 | $1.17 | |
BSC | <0.01% | $593.21 | 0.0019399 | $1.15 | |
BSC | <0.01% | $0.330125 | 3.3561 | $1.11 | |
BSC | <0.01% | $0.918646 | 1.1984 | $1.1 | |
BSC | <0.01% | $0.000012 | 89,477.1651 | $1.1 | |
BSC | <0.01% | $2.46 | 0.4443 | $1.09 | |
BSC | <0.01% | $0.012934 | 82.8162 | $1.07 | |
BSC | <0.01% | $0.004072 | 248.2722 | $1.01 | |
BSC | <0.01% | $4.16 | 0.2421 | $1.01 | |
BSC | <0.01% | $2.93 | 0.3327 | $0.975 | |
BSC | <0.01% | $0.078614 | 12.2818 | $0.9655 | |
BSC | <0.01% | $76.46 | 0.0125 | $0.9552 | |
BSC | <0.01% | $0.070594 | 13.4119 | $0.9467 | |
BSC | <0.01% | $0.242342 | 3.9043 | $0.9461 | |
BSC | <0.01% | $1,601.75 | 0.00057783 | $0.9255 | |
BSC | <0.01% | $0.36629 | 2.522 | $0.9237 | |
BSC | <0.01% | $0.000265 | 3,480.7202 | $0.9214 | |
BSC | <0.01% | $0.025804 | 35.6532 | $0.9199 | |
BSC | <0.01% | $0.017063 | 51.5221 | $0.8791 | |
BSC | <0.01% | $0.178015 | 4.9187 | $0.8756 | |
BSC | <0.01% | $2.49 | 0.3468 | $0.8623 | |
BSC | <0.01% | $0.081267 | 10.4364 | $0.8481 | |
BSC | <0.01% | $0.000132 | 6,296.4791 | $0.8326 | |
BSC | <0.01% | $0.006645 | 123.6074 | $0.8214 | |
BSC | <0.01% | $83,894 | 0.00000975 | $0.8182 | |
BSC | <0.01% | $0.002321 | 339.0612 | $0.787 | |
BSC | <0.01% | $0.014336 | 54.4445 | $0.7805 | |
BSC | <0.01% | $0.079346 | 9.5381 | $0.7568 | |
BSC | <0.01% | $0.000001 | 683,100.2291 | $0.7514 | |
BSC | <0.01% | $0.0038 | 195.5107 | $0.7429 | |
BSC | <0.01% | $0.001073 | 638.4878 | $0.6854 | |
BSC | <0.01% | <$0.000001 | 9,628,290,693.7369 | $0.6848 | |
BSC | <0.01% | $0.001295 | 516.9881 | $0.6693 | |
BSC | <0.01% | $1.14 | 0.584 | $0.6657 | |
BSC | <0.01% | $0.000001 | 561,758.2707 | $0.6628 | |
BSC | <0.01% | $0.161578 | 4.0313 | $0.6513 | |
BSC | <0.01% | $81,354 | 0.0000079 | $0.6428 | |
BSC | <0.01% | $0.001842 | 332.3486 | $0.6122 | |
BSC | <0.01% | $0.017631 | 33.4427 | $0.5896 | |
BSC | <0.01% | $0.295157 | 1.9739 | $0.5826 | |
BSC | <0.01% | $0.00013 | 4,340.0912 | $0.5649 | |
BSC | <0.01% | <$0.000001 | 53,130,865.609 | $0.5613 | |
BSC | <0.01% | $0.004682 | 118.9653 | $0.557 | |
BSC | <0.01% | $0.010876 | 48.6554 | $0.5291 | |
BSC | <0.01% | $0.015138 | 32.3527 | $0.4897 | |
BSC | <0.01% | $0.007788 | 62.6402 | $0.4878 | |
BSC | <0.01% | $0.009648 | 49.0174 | $0.4728 | |
BSC | <0.01% | $0.694318 | 0.6792 | $0.4715 | |
BSC | <0.01% | $0.00632 | 73.1376 | $0.4622 | |
BSC | <0.01% | $0.08585 | 5.1899 | $0.4455 | |
BSC | <0.01% | $0.000015 | 30,000 | $0.4407 | |
BSC | <0.01% | $0.000012 | 35,949.535 | $0.4389 | |
BSC | <0.01% | $0.000205 | 2,069.6124 | $0.4247 | |
BSC | <0.01% | $0.009284 | 45.0544 | $0.4182 | |
BSC | <0.01% | $0.000128 | 3,265.1962 | $0.4182 | |
BSC | <0.01% | $1.19 | 0.3448 | $0.4103 | |
BSC | <0.01% | $0.05648 | 7.1882 | $0.4059 | |
BSC | <0.01% | $0.000912 | 423.9684 | $0.3866 | |
BSC | <0.01% | $2.09 | 0.1795 | $0.3745 | |
BSC | <0.01% | $1,675.56 | 0.00022346 | $0.3744 | |
BSC | <0.01% | $0.002755 | 135.9402 | $0.3744 | |
BSC | <0.01% | $0.000314 | 1,147.7241 | $0.3605 | |
BSC | <0.01% | $0.108135 | 3.2816 | $0.3548 | |
BSC | <0.01% | $0.058299 | 5.9524 | $0.347 | |
BSC | <0.01% | $85,001 | 0.00000406 | $0.3451 | |
BSC | <0.01% | $0.000549 | 624.3904 | $0.3429 | |
BSC | <0.01% | $0.278098 | 1.2194 | $0.3391 | |
BSC | <0.01% | <$0.000001 | 27,206,346.0128 | $0.3221 | |
BSC | <0.01% | $0.013111 | 23.2482 | $0.3047 | |
BSC | <0.01% | $0.003789 | 78.6172 | $0.2978 | |
BSC | <0.01% | $0.000326 | 912.8418 | $0.2976 | |
BSC | <0.01% | $0.000008 | 35,339.1556 | $0.2911 | |
BSC | <0.01% | $0.013965 | 20.7536 | $0.2898 | |
BSC | <0.01% | <$0.000001 | 4,632,542.0165 | $0.2884 | |
BSC | <0.01% | <$0.000001 | 30,254,867.4291 | $0.288 | |
BSC | <0.01% | $0.000089 | 3,224.6558 | $0.286 | |
BSC | <0.01% | $0.01763 | 16.1822 | $0.2852 | |
BSC | <0.01% | $0.000617 | 459.6164 | $0.2834 | |
BSC | <0.01% | $0.008696 | 32.3928 | $0.2816 | |
BSC | <0.01% | $0.000161 | 1,738.0143 | $0.2798 | |
BSC | <0.01% | $0.025669 | 10.805 | $0.2773 | |
BSC | <0.01% | $0.020529 | 13.48 | $0.2767 | |
BSC | <0.01% | $0.000085 | 3,243.0048 | $0.2762 | |
BSC | <0.01% | $0.000164 | 1,665.5791 | $0.2739 | |
BSC | <0.01% | $0.011885 | 22.765 | $0.2705 | |
BSC | <0.01% | $0.000006 | 41,127.0951 | $0.2651 | |
BSC | <0.01% | $0.000384 | 671.7231 | $0.2579 | |
BSC | <0.01% | $84,659 | 0.00000304 | $0.2571 | |
BSC | <0.01% | $139.83 | 0.00183228 | $0.2562 | |
BSC | <0.01% | $0.06634 | 3.7756 | $0.2504 | |
BSC | <0.01% | $0.238433 | 1.02 | $0.2431 | |
BSC | <0.01% | $0.018505 | 12.8644 | $0.238 | |
BSC | <0.01% | $0.001659 | 143.051 | $0.2373 | |
BSC | <0.01% | $0.073965 | 3.2003 | $0.2367 | |
BSC | <0.01% | $0.007552 | 31.3197 | $0.2365 | |
BSC | <0.01% | $0.000012 | 19,205.5003 | $0.235 | |
BSC | <0.01% | $0.029758 | 7.8816 | $0.2345 | |
BSC | <0.01% | <$0.000001 | 181,829,476.7513 | $0.2332 | |
BSC | <0.01% | $0.904097 | 0.2519 | $0.2277 | |
BSC | <0.01% | $0.00493 | 45.4003 | $0.2238 | |
BSC | <0.01% | $0.067881 | 3.1535 | $0.214 | |
BSC | <0.01% | $0.547026 | 0.3856 | $0.2109 | |
BSC | <0.01% | $0.504491 | 0.4167 | $0.2102 | |
BSC | <0.01% | $1 | 0.2082 | $0.2082 | |
BSC | <0.01% | $0.011575 | 17.7771 | $0.2057 | |
BSC | <0.01% | $0.934337 | 0.2186 | $0.2042 | |
BSC | <0.01% | $0.367957 | 0.5538 | $0.2037 | |
BSC | <0.01% | $0.001788 | 113.8701 | $0.2035 | |
BSC | <0.01% | $0.171693 | 1.1824 | $0.203 | |
BSC | <0.01% | $9.24 | 0.0219 | $0.202 | |
BSC | <0.01% | $0.090298 | 2.1945 | $0.1981 | |
BSC | <0.01% | $0.000002 | 89,869.3141 | $0.195 | |
BSC | <0.01% | $0.001033 | 187.1072 | $0.1933 | |
BSC | <0.01% | $0.244351 | 0.7719 | $0.1886 | |
BSC | <0.01% | $0.013066 | 14.3643 | $0.1876 | |
BSC | <0.01% | $0.999804 | 0.185 | $0.1849 | |
BSC | <0.01% | $0.00822 | 22.3594 | $0.1837 | |
BSC | <0.01% | $0.024611 | 7.3417 | $0.1806 | |
BSC | <0.01% | $0.014435 | 12.4945 | $0.1803 | |
BSC | <0.01% | $0.000133 | 1,355.2055 | $0.1801 | |
BSC | <0.01% | $5.35 | 0.0331 | $0.177 | |
BSC | <0.01% | $0.002022 | 86.9476 | $0.1758 | |
BSC | <0.01% | $0.000001 | 131,692.5093 | $0.1738 | |
BSC | <0.01% | $0.502061 | 0.3431 | $0.1722 | |
BSC | <0.01% | $0.007726 | 21.9051 | $0.1692 | |
BSC | <0.01% | $0.00361 | 45.9531 | $0.1658 | |
BSC | <0.01% | $0.013079 | 12.6628 | $0.1656 | |
BSC | <0.01% | $39.67 | 0.00410948 | $0.163 | |
BSC | <0.01% | $0.00299 | 54.2706 | $0.1622 | |
BSC | <0.01% | $0.000023 | 7,062.0998 | $0.1618 | |
BSC | <0.01% | $0.31041 | 0.5087 | $0.1579 | |
BSC | <0.01% | $0.009578 | 16.4221 | $0.1572 | |
BSC | <0.01% | $0.002138 | 73.3808 | $0.1568 | |
BSC | <0.01% | $0.038457 | 4.0676 | $0.1564 | |
BSC | <0.01% | $0.07019 | 2.2278 | $0.1563 | |
BSC | <0.01% | $0.000598 | 259.5823 | $0.1552 | |
BSC | <0.01% | $0.000057 | 2,706.7036 | $0.1546 | |
BSC | <0.01% | $0.000872 | 176.5728 | $0.154 | |
BSC | <0.01% | $0.179996 | 0.8481 | $0.1526 | |
BSC | <0.01% | $0.999976 | 0.1496 | $0.1496 | |
BSC | <0.01% | $0.000155 | 960.5992 | $0.1489 | |
BSC | <0.01% | $0.000372 | 396.3157 | $0.1475 | |
BSC | <0.01% | $0.060707 | 2.4304 | $0.1475 | |
BSC | <0.01% | $0.002708 | 54.0486 | $0.1463 | |
BSC | <0.01% | $84,983.43 | 0.0000017 | $0.1443 | |
BSC | <0.01% | $0.085688 | 1.6784 | $0.1438 | |
BSC | <0.01% | $0.07377 | 1.8928 | $0.1396 | |
BSC | <0.01% | $0.006421 | 21.5347 | $0.1382 | |
BSC | <0.01% | $52.23 | 0.00256295 | $0.1338 | |
BSC | <0.01% | $0.000036 | 3,694.58 | $0.1333 | |
BSC | <0.01% | $0.001424 | 93.3185 | $0.1328 | |
BSC | <0.01% | $0.174982 | 0.7436 | $0.1301 | |
BSC | <0.01% | $0.685544 | 0.1879 | $0.1287 | |
BSC | <0.01% | $0.016556 | 7.7082 | $0.1276 | |
BSC | <0.01% | $0.054273 | 2.2818 | $0.1238 | |
BSC | <0.01% | $0.055722 | 2.2062 | $0.1229 | |
BSC | <0.01% | $0.004043 | 30.365 | $0.1227 | |
BSC | <0.01% | $0.000001 | 200,127.8989 | $0.1226 | |
BSC | <0.01% | $0.028199 | 4.3209 | $0.1218 | |
BSC | <0.01% | $0.000041 | 2,887.5975 | $0.1188 | |
BSC | <0.01% | $0.052756 | 2.2397 | $0.1181 | |
BSC | <0.01% | $0.002706 | 43.5183 | $0.1177 | |
BSC | <0.01% | $0.019317 | 6.0527 | $0.1169 | |
BSC | <0.01% | $0.021812 | 5.3418 | $0.1165 | |
BSC | <0.01% | $0.207162 | 0.5567 | $0.1153 | |
BSC | <0.01% | $0.028123 | 4.0354 | $0.1134 | |
BSC | <0.01% | $0.018693 | 6.044 | $0.1129 | |
BSC | <0.01% | $0.013661 | 8.2196 | $0.1122 | |
BSC | <0.01% | $0.528873 | 0.2122 | $0.1122 | |
BSC | <0.01% | $0.000006 | 19,974.1693 | $0.11 | |
BSC | <0.01% | $0.006857 | 15.9476 | $0.1093 | |
BSC | <0.01% | $11.73 | 0.0089003 | $0.1044 | |
BSC | <0.01% | $0.998022 | 0.1036 | $0.1033 | |
BSC | <0.01% | $2.3 | 0.0447 | $0.1027 | |
BSC | <0.01% | $0.053426 | 1.8979 | $0.1013 | |
ETH | 1.42% | $0.99998 | 179.3909 | $179.39 | |
ETH | 1.05% | $0.480246 | 276.4713 | $132.77 | |
ETH | 0.55% | $1,605.06 | 0.043 | $69 | |
ETH | 0.20% | $0.066904 | 384.2989 | $25.71 | |
ETH | 0.13% | $0.008338 | 1,981.9716 | $16.53 | |
ETH | 0.08% | $0.160833 | 64.3726 | $10.35 | |
ETH | 0.08% | $0.129754 | 78.3399 | $10.16 | |
ETH | 0.08% | $0.008847 | 1,113.908 | $9.85 | |
ETH | 0.08% | $1.05 | 9.2339 | $9.68 | |
ETH | 0.08% | $312.01 | 0.0306 | $9.56 | |
ETH | 0.08% | $0.056657 | 166.8879 | $9.46 | |
ETH | 0.07% | $108.62 | 0.0869 | $9.44 | |
ETH | 0.07% | $0.055889 | 168.1191 | $9.4 | |
ETH | 0.07% | $0.999948 | 9.3069 | $9.31 | |
ETH | 0.07% | $1.76 | 5.2621 | $9.26 | |
ETH | 0.07% | $0.000532 | 17,062.657 | $9.07 | |
ETH | 0.07% | $0.000001 | 8,452,686.782 | $8.96 | |
ETH | 0.07% | $0.000002 | 4,086,750.4267 | $8.87 | |
ETH | 0.07% | $0.277067 | 31.9292 | $8.85 | |
ETH | 0.07% | $0.040053 | 219.5624 | $8.79 | |
ETH | 0.07% | $1,671.58 | 0.00522695 | $8.74 | |
ETH | 0.07% | $0.825756 | 10.5455 | $8.71 | |
ETH | 0.07% | $0.027061 | 317.8056 | $8.6 | |
ETH | 0.07% | $0.123605 | 69.3792 | $8.58 | |
ETH | 0.07% | $0.001224 | 6,962.0381 | $8.52 | |
ETH | 0.07% | $0.001664 | 5,111.9815 | $8.51 | |
ETH | 0.07% | $1.75 | 4.8599 | $8.5 | |
ETH | 0.07% | $0.004445 | 1,880.05 | $8.36 | |
ETH | 0.07% | $13.62 | 0.6087 | $8.29 | |
ETH | 0.07% | $0.000004 | 2,202,065.2464 | $8.28 | |
ETH | 0.06% | $0.021588 | 376.4873 | $8.13 | |
ETH | 0.06% | $0.99994 | 8.0285 | $8.03 | |
ETH | 0.06% | $0.06261 | 127.3325 | $7.97 | |
ETH | 0.06% | $0.138881 | 57.1085 | $7.93 | |
ETH | 0.06% | $0.000003 | 2,406,586.3854 | $7.89 | |
ETH | 0.06% | $3.91 | 1.9781 | $7.73 | |
ETH | 0.06% | $0.278098 | 27.5031 | $7.65 | |
ETH | 0.06% | $0.001871 | 4,054.1197 | $7.59 | |
ETH | 0.06% | $0.38741 | 19.4289 | $7.53 | |
ETH | 0.06% | $0.084739 | 86.6957 | $7.35 | |
ETH | 0.06% | $0.021996 | 333.2672 | $7.33 | |
ETH | 0.06% | $0.260719 | 28.0209 | $7.31 | |
ETH | 0.06% | $0.000471 | 15,454.5877 | $7.28 | |
ETH | 0.06% | $0.37718 | 19.1125 | $7.21 | |
ETH | 0.06% | $22.79 | 0.3155 | $7.19 | |
ETH | 0.06% | $0.997759 | 7.2048 | $7.19 | |
ETH | 0.06% | $0.024458 | 292.927 | $7.16 | |
ETH | 0.06% | $0.000004 | 1,919,167.4733 | $7.15 | |
ETH | 0.06% | $0.000017 | 417,614.8336 | $7.15 | |
ETH | 0.06% | $0.011794 | 606.0529 | $7.15 | |
ETH | 0.06% | $0.165458 | 42.8961 | $7.1 | |
ETH | 0.06% | <$0.000001 | 1,365,400,612.1627 | $7.05 | |
ETH | 0.06% | $0.000504 | 13,743.0508 | $6.93 | |
ETH | 0.05% | $2.35 | 2.8927 | $6.81 | |
ETH | 0.05% | $0.026714 | 253.8928 | $6.78 | |
ETH | 0.05% | $0.000001 | 4,872,758.5536 | $6.77 | |
ETH | 0.05% | $0.027061 | 249.6301 | $6.76 | |
ETH | 0.05% | $0.48753 | 13.8205 | $6.74 | |
ETH | 0.05% | $0.019317 | 342.8956 | $6.62 | |
ETH | 0.05% | $1,752.12 | 0.00373323 | $6.54 | |
ETH | 0.05% | $0.000001 | 6,804,523.7108 | $6.47 | |
ETH | 0.05% | $26.64 | 0.2427 | $6.47 | |
ETH | 0.05% | $0.01957 | 328.1456 | $6.42 | |
ETH | 0.05% | $0.145292 | 44.1306 | $6.41 | |
ETH | 0.05% | $0.000012 | 523,101.8665 | $6.4 | |
ETH | 0.05% | $0.100757 | 63.5276 | $6.4 | |
ETH | 0.05% | $0.060186 | 105.1932 | $6.33 | |
ETH | 0.05% | $0.007032 | 897.9985 | $6.31 | |
ETH | 0.05% | $0.449159 | 13.9684 | $6.27 | |
ETH | 0.05% | $0.003389 | 1,850.8156 | $6.27 | |
ETH | 0.05% | $0.06028 | 104.0163 | $6.27 | |
ETH | 0.05% | $0.250868 | 24.6969 | $6.2 | |
ETH | 0.05% | $0.017509 | 353.6332 | $6.19 | |
ETH | 0.05% | $0.002022 | 3,054.0527 | $6.17 | |
ETH | 0.05% | $0.528873 | 11.6136 | $6.14 | |
ETH | 0.05% | $0.155626 | 39.0954 | $6.08 | |
ETH | 0.05% | $0.016977 | 350.6023 | $5.95 | |
ETH | 0.05% | $0.701471 | 8.4162 | $5.9 | |
ETH | 0.05% | <$0.000001 | 123,060,856.6667 | $5.88 | |
ETH | 0.05% | $0.004758 | 1,228.8484 | $5.85 | |
ETH | 0.05% | <$0.000001 | 1,453,974,907.1729 | $5.8 | |
ETH | 0.04% | $53.48 | 0.103 | $5.51 | |
ETH | 0.04% | $0.013008 | 421.7596 | $5.49 | |
ETH | 0.04% | $0.240123 | 22.8253 | $5.48 | |
ETH | 0.04% | $0.00832 | 657.0115 | $5.47 | |
ETH | 0.04% | $0.001328 | 4,114.4031 | $5.47 | |
ETH | 0.04% | $0.021364 | 254.5249 | $5.44 | |
ETH | 0.04% | $2.57 | 2.1103 | $5.42 | |
ETH | 0.04% | $19.57 | 0.2704 | $5.29 | |
ETH | 0.04% | $84,849 | 0.00006235 | $5.29 | |
ETH | 0.04% | $5.34 | 0.99 | $5.29 | |
ETH | 0.04% | $0.780746 | 6.6514 | $5.19 | |
ETH | 0.04% | $0.730895 | 7.0409 | $5.15 | |
ETH | 0.04% | $0.007762 | 661.7375 | $5.14 | |
ETH | 0.04% | $0.06445 | 79.4874 | $5.12 | |
ETH | 0.04% | $0.000353 | 14,415.4173 | $5.08 | |
ETH | 0.04% | $0.193917 | 26.1695 | $5.07 | |
ETH | 0.04% | $1.93 | 2.5504 | $4.93 | |
ETH | 0.04% | $1.14 | 4.2793 | $4.88 | |
ETH | 0.04% | $0.761724 | 6.3596 | $4.84 | |
ETH | 0.04% | $0.004661 | 1,039.1399 | $4.84 | |
ETH | 0.04% | $0.001546 | 3,132.3092 | $4.84 | |
ETH | 0.04% | $1.99 | 2.4276 | $4.83 | |
ETH | 0.04% | $0.110846 | 43.5529 | $4.83 | |
ETH | 0.04% | $0.467213 | 10.3301 | $4.83 | |
ETH | 0.04% | $0.119485 | 40.3143 | $4.82 | |
ETH | 0.04% | $0.001956 | 2,445.3397 | $4.78 | |
ETH | 0.04% | $31.28 | 0.1497 | $4.68 | |
ETH | 0.04% | $0.05281 | 88.5991 | $4.68 | |
ETH | 0.04% | $0.065994 | 70.8526 | $4.68 | |
ETH | 0.04% | $1 | 4.6711 | $4.67 | |
ETH | 0.04% | $1.14 | 4.0771 | $4.65 | |
ETH | 0.04% | $0.000002 | 1,939,996.8476 | $4.64 | |
ETH | 0.04% | $0.000002 | 2,418,140.5654 | $4.62 | |
ETH | 0.04% | $0.000008 | 541,714.0271 | $4.58 | |
ETH | 0.04% | $0.063227 | 72.0242 | $4.55 | |
ETH | 0.03% | $0.000954 | 4,607.129 | $4.4 | |
ETH | 0.03% | $0.569728 | 7.53 | $4.29 | |
ETH | 0.03% | $0.131306 | 32.586 | $4.28 | |
ETH | 0.03% | $0.05509 | 77.159 | $4.25 | |
ETH | 0.03% | $0.012637 | 335.694 | $4.24 | |
ETH | 0.03% | $0.512062 | 8.2337 | $4.22 | |
ETH | 0.03% | $0.161954 | 25.5703 | $4.14 | |
ETH | 0.03% | $0.041497 | 99.3389 | $4.12 | |
ETH | 0.03% | $0.50199 | 8.1781 | $4.11 | |
ETH | 0.03% | $0.000844 | 4,807.9124 | $4.06 | |
ETH | 0.03% | $0.008521 | 476.2595 | $4.06 | |
ETH | 0.03% | $0.241489 | 16.7419 | $4.04 | |
ETH | 0.03% | $0.000123 | 32,956.9267 | $4.04 | |
ETH | 0.03% | $0.001134 | 3,506.2974 | $3.98 | |
ETH | 0.03% | $0.52187 | 7.5723 | $3.95 | |
ETH | 0.03% | $1,602.64 | 0.00244891 | $3.92 | |
ETH | 0.03% | $0.036604 | 106.9095 | $3.91 | |
ETH | 0.03% | $0.015667 | 249.3811 | $3.91 | |
ETH | 0.03% | <$0.000001 | 30,134,161.7043 | $3.89 | |
ETH | 0.03% | $7.95 | 0.4851 | $3.86 | |
ETH | 0.03% | $0.036439 | 105.7068 | $3.85 | |
ETH | 0.03% | $0.255975 | 14.9668 | $3.83 | |
ETH | 0.03% | $0.000021 | 182,767.1258 | $3.79 | |
ETH | 0.03% | $0.606256 | 6.2187 | $3.77 | |
ETH | 0.03% | $1.08 | 3.4818 | $3.76 | |
ETH | 0.03% | $0.220874 | 16.9357 | $3.74 | |
ETH | 0.03% | $1.9 | 1.935 | $3.68 | |
ETH | 0.03% | $0.025384 | 144.2199 | $3.66 | |
ETH | 0.03% | $0.00001 | 375,321.8005 | $3.64 | |
ETH | 0.03% | $2.3 | 1.5724 | $3.62 | |
ETH | 0.03% | $0.998748 | 3.6012 | $3.6 | |
ETH | 0.03% | $0.009173 | 390.0733 | $3.58 | |
ETH | 0.03% | $0.004873 | 732.3823 | $3.57 | |
ETH | 0.03% | $0.207667 | 17.1302 | $3.56 | |
ETH | 0.03% | $0.005357 | 661.1775 | $3.54 | |
ETH | 0.03% | $0.001205 | 2,927.0926 | $3.53 | |
ETH | 0.03% | $84,186 | 0.00004152 | $3.5 | |
ETH | 0.03% | $0.000663 | 5,217.6592 | $3.46 | |
ETH | 0.03% | $21.68 | 0.1591 | $3.45 | |
ETH | 0.03% | $1.07 | 3.2089 | $3.45 | |
ETH | 0.03% | $1,674.97 | 0.00205711 | $3.45 | |
ETH | 0.03% | $0.104866 | 32.7728 | $3.44 | |
ETH | 0.03% | $0.118791 | 28.7305 | $3.41 | |
ETH | 0.03% | $0.081301 | 41.7508 | $3.39 | |
ETH | 0.03% | $1,923.42 | 0.00175727 | $3.38 | |
ETH | 0.03% | $0.000159 | 21,187.1742 | $3.36 | |
ETH | 0.03% | $0.000022 | 149,332.7607 | $3.33 | |
ETH | 0.03% | $0.010372 | 318.1569 | $3.3 | |
ETH | 0.03% | <$0.000001 | 2,556,526,383.204 | $3.28 | |
ETH | 0.03% | $2.16 | 1.4873 | $3.21 | |
ETH | 0.03% | $0.296742 | 10.8173 | $3.21 | |
ETH | 0.03% | $0.003244 | 988.6556 | $3.21 | |
ETH | 0.03% | $0.027187 | 117.8648 | $3.2 | |
ETH | 0.03% | $0.008025 | 398.713 | $3.2 | |
ETH | 0.03% | $1,703.27 | 0.00186383 | $3.17 | |
ETH | 0.03% | $0.129741 | 24.4166 | $3.17 | |
ETH | 0.03% | $0.623851 | 5.0771 | $3.17 | |
ETH | 0.03% | $0.000372 | 8,500.7844 | $3.16 | |
ETH | 0.02% | $0.073756 | 42.6818 | $3.15 | |
ETH | 0.02% | <$0.000001 | 91,025,549.2645 | $3.14 | |
ETH | 0.02% | $8.26 | 0.379 | $3.13 | |
ETH | 0.02% | $0.293195 | 10.3859 | $3.05 | |
ETH | 0.02% | $0.000003 | 1,147,950.6712 | $3.04 | |
ETH | 0.02% | $0.000205 | 14,784.1139 | $3.04 | |
ETH | 0.02% | $0.000561 | 5,406.7135 | $3.03 | |
ETH | 0.02% | $0.058459 | 50.9562 | $2.98 | |
ETH | 0.02% | $0.005565 | 534.008 | $2.97 | |
ETH | 0.02% | $84,957 | 0.00003483 | $2.96 | |
ETH | 0.02% | $0.060707 | 48.7415 | $2.96 | |
ETH | 0.02% | $0.377107 | 7.797 | $2.94 | |
ETH | 0.02% | $0.000041 | 70,843.1362 | $2.93 | |
ETH | 0.02% | $6.46 | 0.4523 | $2.92 | |
ETH | 0.02% | $0.00793 | 362.5578 | $2.88 | |
ETH | 0.02% | $0.019911 | 144.1388 | $2.87 | |
ETH | 0.02% | $0.046553 | 61.4151 | $2.86 | |
ETH | 0.02% | $0.483664 | 5.8948 | $2.85 | |
ETH | 0.02% | $0.028807 | 98.6424 | $2.84 | |
ETH | 0.02% | $0.000503 | 5,594.055 | $2.81 | |
ETH | 0.02% | $0.152312 | 18.4609 | $2.81 | |
ETH | 0.02% | $1,675.56 | 0.00165199 | $2.77 | |
ETH | 0.02% | $0.041474 | 66.7397 | $2.77 | |
ETH | 0.02% | $0.012733 | 216.276 | $2.75 | |
ETH | 0.02% | $0.000115 | 23,786.1856 | $2.74 | |
ETH | 0.02% | $0.00706 | 385.7011 | $2.72 | |
ETH | 0.02% | $0.000176 | 15,415.4914 | $2.71 | |
ETH | 0.02% | $1,606.29 | 0.00168193 | $2.7 | |
ETH | 0.02% | $0.021351 | 123.6798 | $2.64 | |
ETH | 0.02% | $0.000004 | 644,944.2146 | $2.64 | |
ETH | 0.02% | $0.002056 | 1,275.6183 | $2.62 | |
ETH | 0.02% | $0.03468 | 75.0631 | $2.6 | |
ETH | 0.02% | $7.14 | 0.3591 | $2.56 | |
ETH | 0.02% | $0.203562 | 12.5792 | $2.56 | |
ETH | 0.02% | $1.73 | 1.4784 | $2.56 | |
ETH | 0.02% | $0.9998 | 2.5317 | $2.53 | |
ETH | 0.02% | $0.043575 | 57.9147 | $2.52 | |
ETH | 0.02% | <$0.000001 | 7,768,763.9887 | $2.48 | |
ETH | 0.02% | $0.013575 | 182.7497 | $2.48 | |
ETH | 0.02% | $0.000001 | 4,047,446.9322 | $2.48 | |
ETH | 0.02% | $0.005332 | 462.273 | $2.46 | |
ETH | 0.02% | <$0.000001 | 31,281,777.0459 | $2.45 | |
ETH | 0.02% | $0.087191 | 27.6902 | $2.41 | |
ETH | 0.02% | $0.009478 | 254.5532 | $2.41 | |
ETH | 0.02% | $0.016493 | 145.7316 | $2.4 | |
ETH | 0.02% | $0.011935 | 199.9179 | $2.39 | |
ETH | 0.02% | $0.001328 | 1,791.2569 | $2.38 | |
ETH | 0.02% | $273.64 | 0.00855878 | $2.34 | |
ETH | 0.02% | $0.001278 | 1,829.9831 | $2.34 | |
ETH | 0.02% | <$0.000001 | 248,661,611.5769 | $2.33 | |
ETH | 0.02% | <$0.000001 | 39,426,401.3577 | $2.31 | |
ETH | 0.02% | $0.000741 | 3,115.7843 | $2.31 | |
ETH | 0.02% | $0.012259 | 187.6155 | $2.3 | |
ETH | 0.02% | $0.002085 | 1,095.9744 | $2.29 | |
ETH | 0.02% | $0.000466 | 4,889.6405 | $2.28 | |
ETH | 0.02% | $0.171591 | 13.1853 | $2.26 | |
ETH | 0.02% | $0.008792 | 256.645 | $2.26 | |
ETH | 0.02% | $0.066334 | 33.5995 | $2.23 | |
ETH | 0.02% | $1.93 | 1.1539 | $2.23 | |
ETH | 0.02% | $0.002745 | 806.802 | $2.21 | |
ETH | 0.02% | $5.45 | 0.4062 | $2.21 | |
ETH | 0.02% | $0.452413 | 4.8473 | $2.19 | |
ETH | 0.02% | $0.000797 | 2,750.5716 | $2.19 | |
ETH | 0.02% | $0.094979 | 22.954 | $2.18 | |
ETH | 0.02% | $0.000867 | 2,504.3365 | $2.17 | |
ETH | 0.02% | $0.000499 | 4,336.2316 | $2.16 | |
ETH | 0.02% | $0.057592 | 37.3907 | $2.15 | |
ETH | 0.02% | $1 | 2.1492 | $2.15 | |
ETH | 0.02% | $0.029446 | 72.6129 | $2.14 | |
ETH | 0.02% | $85,001 | 0.00002501 | $2.13 | |
ETH | 0.02% | $0.10712 | 19.6799 | $2.11 | |
ETH | 0.02% | $85,125 | 0.0000247 | $2.1 | |
ETH | 0.02% | $0.001016 | 2,058.7375 | $2.09 | |
ETH | 0.02% | <$0.000001 | 9,566,370.6545 | $2.09 | |
ETH | 0.02% | $0.070344 | 29.6163 | $2.08 | |
ETH | 0.02% | $0.01277 | 163.1067 | $2.08 | |
ETH | 0.02% | $0.009078 | 228.8307 | $2.08 | |
ETH | 0.02% | $0.001835 | 1,119.7251 | $2.05 | |
ETH | 0.02% | $0.808105 | 2.5391 | $2.05 | |
ETH | 0.02% | $0.035894 | 57.1627 | $2.05 | |
ETH | 0.02% | $0.000058 | 35,139.9541 | $2.04 | |
ETH | 0.02% | $0.073965 | 27.5703 | $2.04 | |
ETH | 0.02% | $0.000758 | 2,691.3606 | $2.04 | |
ETH | 0.02% | $0.000154 | 13,187.7449 | $2.04 | |
ETH | 0.02% | $1.02 | 1.9763 | $2.02 | |
ETH | 0.02% | $0.678537 | 2.9619 | $2.01 | |
ETH | 0.02% | $0.019231 | 104.4735 | $2.01 | |
ETH | 0.02% | $0.01617 | 123.4592 | $2 | |
ETH | 0.02% | $0.011635 | 170.5825 | $1.98 | |
ETH | 0.02% | $83,894 | 0.00002349 | $1.97 | |
ETH | 0.02% | $1,709.15 | 0.00115167 | $1.97 | |
ETH | 0.02% | $0.167746 | 11.6343 | $1.95 | |
ETH | 0.02% | $0.000372 | 5,236.0893 | $1.95 | |
ETH | 0.02% | $5.25 | 0.3696 | $1.94 | |
ETH | 0.02% | $0.00362 | 535.539 | $1.94 | |
ETH | 0.02% | $0.161759 | 11.8835 | $1.92 | |
ETH | 0.02% | $1,804.03 | 0.00106319 | $1.92 | |
ETH | 0.02% | $0.006306 | 302.9588 | $1.91 | |
ETH | 0.02% | $0.096048 | 19.7132 | $1.89 | |
ETH | 0.02% | $0.148196 | 12.7767 | $1.89 | |
ETH | 0.01% | $0.017133 | 110.2443 | $1.89 | |
ETH | 0.01% | $3.98 | 0.4736 | $1.89 | |
ETH | 0.01% | $3.99 | 0.4704 | $1.88 | |
ETH | 0.01% | $0.02846 | 65.5106 | $1.86 | |
ETH | 0.01% | $0.000212 | 8,705.6478 | $1.85 | |
ETH | 0.01% | $0.049595 | 36.8509 | $1.83 | |
ETH | 0.01% | $0.180492 | 10.1126 | $1.83 | |
ETH | 0.01% | $0.010265 | 177.6813 | $1.82 | |
ETH | 0.01% | $0.125252 | 14.5166 | $1.82 | |
ETH | 0.01% | <$0.000001 | 305,967,321.7631 | $1.78 | |
ETH | 0.01% | $1.35 | 1.3177 | $1.78 | |
ETH | 0.01% | $4.46 | 0.3977 | $1.77 | |
ETH | 0.01% | $0.00006 | 29,612.1996 | $1.77 | |
ETH | 0.01% | $0.000749 | 2,341.0036 | $1.75 | |
ETH | 0.01% | $0.018517 | 94.0518 | $1.74 | |
ETH | 0.01% | $0.028643 | 60.6432 | $1.74 | |
ETH | 0.01% | $0.058634 | 29.4977 | $1.73 | |
ETH | 0.01% | $0.133045 | 12.9698 | $1.73 | |
ETH | 0.01% | $0.003796 | 452.8364 | $1.72 | |
ETH | 0.01% | $0.000102 | 16,693.4274 | $1.71 | |
ETH | 0.01% | $0.694918 | 2.4465 | $1.7 | |
ETH | 0.01% | $0.02206 | 77.0346 | $1.7 | |
ETH | 0.01% | $0.001129 | 1,505.268 | $1.7 | |
ETH | 0.01% | $63.57 | 0.0265 | $1.69 | |
ETH | 0.01% | <$0.000001 | 2,002,449,944.5909 | $1.68 | |
ETH | 0.01% | $0.000338 | 4,928.2781 | $1.67 | |
ETH | 0.01% | $0.58201 | 2.8621 | $1.67 | |
ETH | 0.01% | $0.000378 | 4,357.0078 | $1.65 | |
ETH | 0.01% | $0.998022 | 1.6407 | $1.64 | |
ETH | 0.01% | <$0.000001 | 4,104,907.2099 | $1.63 | |
ETH | 0.01% | $0.00144 | 1,130.8097 | $1.63 | |
ETH | 0.01% | <$0.000001 | 1,714,515,204.1416 | $1.61 | |
ETH | 0.01% | $0.003641 | 438.8185 | $1.6 | |
ETH | 0.01% | $0.000287 | 5,454.2734 | $1.57 | |
ETH | 0.01% | $0.01763 | 88.6807 | $1.56 | |
ETH | 0.01% | $0.245723 | 6.3436 | $1.56 | |
ETH | 0.01% | $0.001664 | 929.8375 | $1.55 | |
ETH | 0.01% | $0.000003 | 590,422.7471 | $1.54 | |
ETH | 0.01% | $0.006146 | 247.9221 | $1.52 | |
ETH | 0.01% | $0.367957 | 4.1393 | $1.52 | |
ETH | 0.01% | $0.472052 | 3.2265 | $1.52 | |
ETH | 0.01% | $0.00039 | 3,902.1673 | $1.52 | |
ETH | 0.01% | $0.000003 | 553,086.7376 | $1.52 | |
ETH | 0.01% | $0.213817 | 7.0505 | $1.51 | |
ETH | 0.01% | $0.006518 | 228.8259 | $1.49 | |
ETH | 0.01% | $0.000003 | 435,883.9411 | $1.49 | |
ETH | 0.01% | $0.008841 | 168.5823 | $1.49 | |
ETH | 0.01% | $0.55283 | 2.688 | $1.49 | |
ETH | 0.01% | $0.584603 | 2.5388 | $1.48 | |
ETH | 0.01% | $0.007945 | 184.3702 | $1.46 | |
ETH | 0.01% | $0.999472 | 1.4653 | $1.46 | |
ETH | 0.01% | $0.000534 | 2,731.9792 | $1.46 | |
ETH | 0.01% | $3.16 | 0.4606 | $1.46 | |
ETH | 0.01% | $0.372593 | 3.8943 | $1.45 | |
ETH | 0.01% | $0.166205 | 8.716 | $1.45 | |
ETH | 0.01% | $0.841449 | 1.6987 | $1.43 | |
ETH | 0.01% | $0.006645 | 214.2868 | $1.42 | |
ETH | 0.01% | $0.000004 | 332,793.0348 | $1.41 | |
ETH | 0.01% | <$0.000001 | 32,002,715.4824 | $1.41 | |
ETH | 0.01% | $0.089999 | 15.6053 | $1.4 | |
ETH | 0.01% | $0.000409 | 3,428.522 | $1.4 | |
ETH | 0.01% | $0.004973 | 281.4436 | $1.4 | |
ETH | 0.01% | $0.000054 | 25,714.4255 | $1.4 | |
ETH | 0.01% | $0.211963 | 6.5665 | $1.39 | |
ETH | 0.01% | $0.320054 | 4.3302 | $1.39 | |
ETH | 0.01% | $0.052298 | 26.1868 | $1.37 | |
ETH | 0.01% | $1.36 | 1.003 | $1.36 | |
ETH | 0.01% | $0.00384 | 347.8804 | $1.34 | |
ETH | 0.01% | $0.194875 | 6.8115 | $1.33 | |
ETH | 0.01% | $4 | 0.3304 | $1.32 | |
ETH | 0.01% | $0.007579 | 173.7835 | $1.32 | |
ETH | 0.01% | $0.018332 | 71.8086 | $1.32 | |
ETH | 0.01% | $1.01 | 1.3036 | $1.32 | |
ETH | 0.01% | $0.759605 | 1.7264 | $1.31 | |
ETH | 0.01% | $0.008784 | 147.7946 | $1.3 | |
ETH | 0.01% | $0.013881 | 92.7061 | $1.29 | |
ETH | 0.01% | <$0.000001 | 6,060,751.7654 | $1.28 | |
ETH | 0.01% | $0.014453 | 88.5218 | $1.28 | |
ETH | 0.01% | $0.094392 | 13.5212 | $1.28 | |
ETH | 0.01% | $0.001235 | 1,031.8235 | $1.27 | |
ETH | 0.01% | $0.007866 | 161.8914 | $1.27 | |
ETH | <0.01% | <$0.000001 | 669,047,885.5284 | $1.25 | |
ETH | <0.01% | <$0.000001 | 4,198,942,093.1761 | $1.25 | |
ETH | <0.01% | <$0.000001 | 2,556,767.3235 | $1.25 | |
ETH | <0.01% | $1 | 1.2398 | $1.24 | |
ETH | <0.01% | $0.000009 | 138,595.6999 | $1.24 | |
ETH | <0.01% | $0.000164 | 7,443.8692 | $1.22 | |
ETH | <0.01% | $1.04 | 1.1734 | $1.22 | |
ETH | <0.01% | $0.011014 | 110.561 | $1.22 | |
ETH | <0.01% | $0.006051 | 200.8152 | $1.22 | |
ETH | <0.01% | $0.279077 | 4.2749 | $1.19 | |
ETH | <0.01% | $0.000003 | 455,416.9957 | $1.19 | |
ETH | <0.01% | $0.000554 | 2,136.4534 | $1.18 | |
ETH | <0.01% | $0.001673 | 706.1741 | $1.18 | |
ETH | <0.01% | $0.009142 | 129.0498 | $1.18 | |
ETH | <0.01% | $0.007575 | 155.2113 | $1.18 | |
ETH | <0.01% | $0.127611 | 9.1539 | $1.17 | |
ETH | <0.01% | $0.026307 | 44.3627 | $1.17 | |
ETH | <0.01% | $0.007976 | 146.0272 | $1.16 | |
ETH | <0.01% | $0.124988 | 9.181 | $1.15 | |
ETH | <0.01% | $0.102623 | 11.1811 | $1.15 | |
ETH | <0.01% | $0.072776 | 15.7284 | $1.14 | |
ETH | <0.01% | $0.031392 | 36.1656 | $1.14 | |
ETH | <0.01% | $0.278444 | 4.0572 | $1.13 | |
ETH | <0.01% | $0.003048 | 367.6562 | $1.12 | |
ETH | <0.01% | $0.009479 | 117.9725 | $1.12 | |
ETH | <0.01% | $0.000204 | 5,453.5704 | $1.11 | |
ETH | <0.01% | $1.12 | 0.9842 | $1.1 | |
ETH | <0.01% | $0.154537 | 7.1146 | $1.1 | |
ETH | <0.01% | $0.001757 | 623.4828 | $1.1 | |
ETH | <0.01% | $0.05041 | 21.7281 | $1.1 | |
ETH | <0.01% | $0.063695 | 17.1443 | $1.09 | |
ETH | <0.01% | <$0.000001 | 88,285,733.9251 | $1.08 | |
ETH | <0.01% | $0.017534 | 61.6552 | $1.08 | |
ETH | <0.01% | $0.00852 | 126.3705 | $1.08 | |
ETH | <0.01% | $0.02866 | 37.5435 | $1.08 | |
ETH | <0.01% | <$0.000001 | 6,239,577.184 | $1.07 | |
ETH | <0.01% | $0.780236 | 1.3768 | $1.07 | |
ETH | <0.01% | $0.99998 | 1.0679 | $1.07 | |
ETH | <0.01% | $0.130707 | 8.0954 | $1.06 | |
ETH | <0.01% | $0.004679 | 226.067 | $1.06 | |
ETH | <0.01% | $1.54 | 0.6868 | $1.06 | |
ETH | <0.01% | $0.000242 | 4,340.6233 | $1.05 | |
ETH | <0.01% | $0.012924 | 80.7536 | $1.04 | |
ETH | <0.01% | $0.067545 | 15.2882 | $1.03 | |
ETH | <0.01% | $0.000089 | 11,584.2349 | $1.03 | |
ETH | <0.01% | $0.071102 | 14.4348 | $1.03 | |
ETH | <0.01% | $0.035647 | 28.6605 | $1.02 | |
ETH | <0.01% | $0.010862 | 94.0576 | $1.02 | |
ETH | <0.01% | $0.002528 | 402.7125 | $1.02 | |
ETH | <0.01% | $0.001354 | 750.1142 | $1.02 | |
ETH | <0.01% | $0.011473 | 88.4025 | $1.01 | |
ETH | <0.01% | $0.00397 | 254.5111 | $1.01 | |
ETH | <0.01% | $0.001174 | 856.346 | $1.01 | |
ETH | <0.01% | $0.027197 | 36.828 | $1 | |
ETH | <0.01% | $0.000197 | 5,070.5723 | $1 | |
ETH | <0.01% | $0.045557 | 21.798 | $0.993 | |
ETH | <0.01% | $0.000708 | 1,393.2168 | $0.9862 | |
ETH | <0.01% | $0.001764 | 558.478 | $0.9854 | |
ETH | <0.01% | <$0.000001 | 4,310,632.7228 | $0.9846 | |
ETH | <0.01% | $0.192452 | 5.0961 | $0.9807 | |
ETH | <0.01% | $0.03228 | 30.3181 | $0.9786 | |
ETH | <0.01% | $0.999361 | 0.9788 | $0.9781 | |
ETH | <0.01% | $0.009396 | 101.5649 | $0.9542 | |
ETH | <0.01% | $0.010525 | 90.2667 | $0.95 | |
ETH | <0.01% | $0.007372 | 127.9964 | $0.9436 | |
ETH | <0.01% | $0.001174 | 803.9008 | $0.9435 | |
ETH | <0.01% | $0.067881 | 13.8978 | $0.9433 | |
ETH | <0.01% | $0.008393 | 111.6478 | $0.937 | |
ETH | <0.01% | $0.000002 | 495,133.7405 | $0.9358 | |
ETH | <0.01% | $0.145309 | 6.3678 | $0.9253 | |
ETH | <0.01% | $0.364361 | 2.5185 | $0.9176 | |
ETH | <0.01% | $19.71 | 0.0466 | $0.9175 | |
ETH | <0.01% | $0.000287 | 3,197.4351 | $0.9166 | |
ETH | <0.01% | $14.71 | 0.0616 | $0.9057 | |
ETH | <0.01% | $0.058138 | 15.5025 | $0.9012 | |
ETH | <0.01% | $0.003386 | 265.5495 | $0.8992 | |
ETH | <0.01% | $0.038944 | 23.0149 | $0.8962 | |
ETH | <0.01% | $1,599.43 | 0.00055639 | $0.8899 | |
ETH | <0.01% | $0.000059 | 15,041.0087 | $0.8895 | |
ETH | <0.01% | $0.630265 | 1.399 | $0.8817 | |
ETH | <0.01% | $0.00168 | 522.9661 | $0.8787 | |
ETH | <0.01% | $0.032259 | 27.153 | $0.8759 | |
ETH | <0.01% | $1,926.37 | 0.0004488 | $0.8645 | |
ETH | <0.01% | $7.37 | 0.1166 | $0.8599 | |
ETH | <0.01% | $0.000402 | 2,131.284 | $0.8568 | |
ETH | <0.01% | $0.000116 | 7,382.0012 | $0.8549 | |
ETH | <0.01% | $0.000449 | 1,899.5248 | $0.8525 | |
ETH | <0.01% | $0.092292 | 9.1489 | $0.8443 | |
ETH | <0.01% | $7.13 | 0.1183 | $0.8433 | |
ETH | <0.01% | $0.01081 | 76.5411 | $0.8274 | |
ETH | <0.01% | $16.48 | 0.05 | $0.8243 | |
ETH | <0.01% | $0.25115 | 3.2694 | $0.8211 | |
ETH | <0.01% | $1,694.35 | 0.00047874 | $0.8111 | |
ETH | <0.01% | $0.18743 | 4.3224 | $0.8101 | |
ETH | <0.01% | $0.997776 | 0.8115 | $0.8096 | |
ETH | <0.01% | $0.027901 | 28.7446 | $0.8019 | |
ETH | <0.01% | $0.000001 | 1,235,504.3858 | $0.8017 | |
ETH | <0.01% | $0.009011 | 87.4529 | $0.788 | |
ETH | <0.01% | $0.024137 | 32.5297 | $0.7851 | |
ETH | <0.01% | $0.104894 | 7.4629 | $0.7828 | |
ETH | <0.01% | $0.267248 | 2.917 | $0.7795 | |
ETH | <0.01% | $0.08585 | 9.0782 | $0.7793 | |
ETH | <0.01% | $0.005123 | 151.2521 | $0.7748 | |
ETH | <0.01% | $0.003048 | 254.1356 | $0.7745 | |
ETH | <0.01% | $0.000001 | 1,333,582.0319 | $0.7743 | |
ETH | <0.01% | $1.31 | 0.5872 | $0.7691 | |
ETH | <0.01% | $0.325798 | 2.3442 | $0.7637 | |
ETH | <0.01% | $0.2544 | 3.001 | $0.7634 | |
ETH | <0.01% | $0.002563 | 297.6475 | $0.763 | |
ETH | <0.01% | $0.010524 | 71.4902 | $0.7523 | |
ETH | <0.01% | <$0.000001 | 498,525,746.8195 | $0.7502 | |
ETH | <0.01% | $0.397252 | 1.886 | $0.7492 | |
ETH | <0.01% | $0.00959 | 77.8969 | $0.747 | |
ETH | <0.01% | $0.000683 | 1,082.8199 | $0.7396 | |
ETH | <0.01% | $0.000001 | 595,351.293 | $0.7309 | |
ETH | <0.01% | $0.000619 | 1,177.962 | $0.7287 | |
ETH | <0.01% | $5,910.1 | 0.00012323 | $0.7283 | |
ETH | <0.01% | <$0.000001 | 14,515,277.8876 | $0.7213 | |
ETH | <0.01% | $0.0191 | 37.697 | $0.72 | |
ETH | <0.01% | $0.001552 | 462.7225 | $0.7183 | |
ETH | <0.01% | $0.010382 | 69.1651 | $0.718 | |
ETH | <0.01% | $0.005105 | 139.9907 | $0.7145 | |
ETH | <0.01% | $0.000001 | 680,160.0234 | $0.7141 | |
ETH | <0.01% | $0.001381 | 515.1411 | $0.7115 | |
ETH | <0.01% | $0.171693 | 4.128 | $0.7087 | |
ETH | <0.01% | $3.13 | 0.226 | $0.7072 | |
ETH | <0.01% | $0.001789 | 391.4718 | $0.7005 | |
ETH | <0.01% | $0.999718 | 0.6991 | $0.6989 | |
ETH | <0.01% | $0.00008 | 8,690.0522 | $0.6977 | |
ETH | <0.01% | $0.000001 | 525,456.2494 | $0.6913 | |
ETH | <0.01% | $0.002556 | 267.6272 | $0.684 | |
ETH | <0.01% | $0.057169 | 11.9621 | $0.6838 | |
ETH | <0.01% | $0.000252 | 2,713.9284 | $0.683 | |
ETH | <0.01% | $0.420956 | 1.6181 | $0.6811 | |
ETH | <0.01% | $0.000001 | 845,955.8928 | $0.6797 | |
ETH | <0.01% | $0.003554 | 190.566 | $0.6772 | |
ETH | <0.01% | $0.257158 | 2.6185 | $0.6733 | |
ETH | <0.01% | $0.03212 | 20.8423 | $0.6694 | |
ETH | <0.01% | $0.010015 | 66.8227 | $0.6692 | |
ETH | <0.01% | $0.000026 | 25,737.5906 | $0.6686 | |
ETH | <0.01% | $0.0019 | 350.7634 | $0.6663 | |
ETH | <0.01% | $0.0088 | 75.5883 | $0.6651 | |
ETH | <0.01% | $0.116143 | 5.7067 | $0.6627 | |
ETH | <0.01% | $82,196.21 | 0.00000805 | $0.6616 | |
ETH | <0.01% | $0.000503 | 1,310.6495 | $0.6592 | |
ETH | <0.01% | $0.000146 | 4,528.4622 | $0.6591 | |
ETH | <0.01% | $0.013467 | 48.8238 | $0.6574 | |
ETH | <0.01% | $0.000656 | 997.3355 | $0.6546 | |
ETH | <0.01% | $0.007613 | 85.4203 | $0.6502 | |
ETH | <0.01% | <$0.000001 | 4,109,169.8725 | $0.649 | |
ETH | <0.01% | $0.020495 | 30.8039 | $0.6313 | |
ETH | <0.01% | $0.145305 | 4.337 | $0.6301 | |
ETH | <0.01% | $0.184756 | 3.3898 | $0.6262 | |
ETH | <0.01% | $0.002254 | 277.3433 | $0.625 | |
ETH | <0.01% | $84,803 | 0.00000736 | $0.6241 | |
ETH | <0.01% | $0.021364 | 29.2023 | $0.6238 | |
ETH | <0.01% | $0.014167 | 43.49 | $0.6161 | |
ETH | <0.01% | $0.04184 | 14.6948 | $0.6148 | |
ETH | <0.01% | $0.000001 | 880,855.032 | $0.6145 | |
ETH | <0.01% | $0.000641 | 957.1023 | $0.6132 | |
ETH | <0.01% | <$0.000001 | 4,475,557.3497 | $0.6115 | |
ETH | <0.01% | $0.000029 | 21,096.9988 | $0.6103 | |
ETH | <0.01% | $0.024269 | 25.1207 | $0.6096 | |
ETH | <0.01% | <$0.000001 | 12,139,123.933 | $0.6061 | |
ETH | <0.01% | $0.000306 | 1,978.2572 | $0.6043 | |
ETH | <0.01% | $0.029349 | 20.5924 | $0.6043 | |
ETH | <0.01% | $0.058178 | 10.3659 | $0.603 | |
ETH | <0.01% | $0.136 | 4.4146 | $0.6003 | |
ETH | <0.01% | $0.011058 | 53.9152 | $0.5961 | |
ETH | <0.01% | $0.99999 | 0.5956 | $0.5956 | |
ETH | <0.01% | $0.000315 | 1,877.6042 | $0.5919 | |
ETH | <0.01% | $0.000204 | 2,887.7586 | $0.5878 | |
ETH | <0.01% | $1,655.65 | 0.0003543 | $0.5865 | |
ETH | <0.01% | $0.005862 | 99.6788 | $0.5843 | |
ETH | <0.01% | $0.001118 | 522.5056 | $0.5839 | |
ETH | <0.01% | $0.015211 | 38.2814 | $0.5823 | |
ETH | <0.01% | $0.006986 | 82.8789 | $0.579 | |
ETH | <0.01% | $0.051984 | 10.9821 | $0.5708 | |
ETH | <0.01% | $0.064879 | 8.7244 | $0.566 | |
ETH | <0.01% | $0.159912 | 3.4916 | $0.5583 | |
ETH | <0.01% | $0.015226 | 36.4724 | $0.5553 | |
ETH | <0.01% | $0.016215 | 34.1711 | $0.554 | |
ETH | <0.01% | $0.015636 | 35.4361 | $0.554 | |
ETH | <0.01% | $0.000936 | 588.2486 | $0.5504 | |
ETH | <0.01% | $0.002458 | 223.3223 | $0.5489 | |
ETH | <0.01% | $0.211191 | 2.5962 | $0.5482 | |
ETH | <0.01% | $0.000783 | 693.6194 | $0.5429 | |
ETH | <0.01% | $0.0003 | 1,807.7449 | $0.5416 | |
ETH | <0.01% | $0.035237 | 15.3469 | $0.5407 | |
ETH | <0.01% | $0.005403 | 99.7458 | $0.5389 | |
ETH | <0.01% | $0.602802 | 0.8924 | $0.5379 | |
ETH | <0.01% | <$0.000001 | 1,685,711,646.0957 | $0.5359 | |
ETH | <0.01% | $0.007188 | 74.3281 | $0.5342 | |
ETH | <0.01% | $0.000002 | 249,854.8813 | $0.5321 | |
ETH | <0.01% | $9.29 | 0.0571 | $0.5301 | |
ETH | <0.01% | <$0.000001 | 2,991,640,776.4028 | $0.5229 | |
ETH | <0.01% | $0.000012 | 44,290.9869 | $0.5221 | |
ETH | <0.01% | $0.001336 | 389.7433 | $0.5207 | |
ETH | <0.01% | $0.60698 | 0.857 | $0.5201 | |
ETH | <0.01% | $140.14 | 0.00369795 | $0.5182 | |
ETH | <0.01% | $0.013158 | 38.9495 | $0.5124 | |
ETH | <0.01% | <$0.000001 | 338,606,893.1196 | $0.5109 | |
ETH | <0.01% | <$0.000001 | 48,391,645.4636 | $0.5087 | |
ETH | <0.01% | $0.001644 | 308.0775 | $0.5064 | |
ETH | <0.01% | $20.89 | 0.0239 | $0.50 | |
ETH | <0.01% | $0.00507 | 98.3158 | $0.4985 | |
ETH | <0.01% | $0.05205 | 9.4912 | $0.494 | |
ETH | <0.01% | $0.00732 | 67.0378 | $0.4907 | |
ETH | <0.01% | $0.054648 | 8.9684 | $0.4901 | |
ETH | <0.01% | $7.28 | 0.0672 | $0.4894 | |
ETH | <0.01% | $0.000384 | 1,270.0559 | $0.4875 | |
ETH | <0.01% | $0.005626 | 86.6176 | $0.4872 | |
ETH | <0.01% | $0.001165 | 416.6518 | $0.4852 | |
ETH | <0.01% | $0.999438 | 0.4824 | $0.4821 | |
ETH | <0.01% | $0.547492 | 0.88 | $0.4818 | |
ETH | <0.01% | <$0.000001 | 4,356,125.6519 | $0.4807 | |
ETH | <0.01% | $2.34 | 0.2045 | $0.4781 | |
ETH | <0.01% | $6.35 | 0.0746 | $0.4739 | |
ETH | <0.01% | $0.006228 | 75.8153 | $0.4722 | |
ETH | <0.01% | $0.000204 | 2,318.2758 | $0.4722 | |
ETH | <0.01% | $0.006656 | 70.252 | $0.4675 | |
ETH | <0.01% | $0.003372 | 138.3851 | $0.4666 | |
ETH | <0.01% | $0.042 | 11.064 | $0.4646 | |
ETH | <0.01% | $0.001185 | 391.0184 | $0.4632 | |
ETH | <0.01% | $0.504405 | 0.9124 | $0.4602 | |
ETH | <0.01% | $0.00066 | 694.929 | $0.4584 | |
ETH | <0.01% | $0.002616 | 174.5622 | $0.4566 | |
ETH | <0.01% | $0.002886 | 157.8786 | $0.4556 | |
ETH | <0.01% | $9.79 | 0.0465 | $0.4553 | |
ETH | <0.01% | $0.027284 | 16.673 | $0.4549 | |
ETH | <0.01% | $2 | 0.2273 | $0.4546 | |
ETH | <0.01% | $0.019568 | 23.0927 | $0.4518 | |
ETH | <0.01% | $0.003229 | 139.8515 | $0.4515 | |
ETH | <0.01% | $0.003259 | 138.3792 | $0.4509 | |
ETH | <0.01% | $0.341912 | 1.3061 | $0.4465 | |
ETH | <0.01% | $0.028106 | 15.787 | $0.4437 | |
ETH | <0.01% | $0.000016 | 27,081.5861 | $0.4433 | |
ETH | <0.01% | $0.007099 | 62.2362 | $0.4418 | |
ETH | <0.01% | $0.004595 | 95.8707 | $0.4405 | |
ETH | <0.01% | $0.000111 | 3,946.3706 | $0.437 | |
ETH | <0.01% | $0.000111 | 3,876.782 | $0.4307 | |
ETH | <0.01% | <$0.000001 | 510,907,082.6379 | $0.428 | |
ETH | <0.01% | $0.03088 | 13.8069 | $0.4263 | |
ETH | <0.01% | $0.073502 | 5.7986 | $0.4262 | |
ETH | <0.01% | $0.482553 | 0.8804 | $0.4248 | |
ETH | <0.01% | $1.11 | 0.38 | $0.4218 | |
ETH | <0.01% | <$0.000001 | 2,289,150.2138 | $0.4214 | |
ETH | <0.01% | $0.036756 | 11.4344 | $0.4202 | |
ETH | <0.01% | $0.235555 | 1.7596 | $0.4144 | |
ETH | <0.01% | $0.004841 | 85.1145 | $0.412 | |
ETH | <0.01% | $0.001478 | 278 | $0.4109 | |
ETH | <0.01% | $0.0113 | 36.0013 | $0.4068 | |
ETH | <0.01% | $0.015017 | 26.8007 | $0.4024 | |
ETH | <0.01% | $0.000002 | 224,095.8008 | $0.4019 | |
ETH | <0.01% | $0.00508 | 78.9201 | $0.4009 | |
ETH | <0.01% | $0.0191 | 20.9912 | $0.4009 | |
ETH | <0.01% | $0.129416 | 3.0607 | $0.3961 | |
ETH | <0.01% | <$0.000001 | 296,502,838.3915 | $0.3922 | |
ETH | <0.01% | $0.003993 | 98.0611 | $0.3916 | |
ETH | <0.01% | $0.999856 | 0.3908 | $0.3907 | |
ETH | <0.01% | $0.074846 | 5.2165 | $0.3904 | |
ETH | <0.01% | $0.000193 | 2,026.0643 | $0.3902 | |
ETH | <0.01% | $0.110103 | 3.5122 | $0.3867 | |
ETH | <0.01% | <$0.000001 | 3,349,022.0012 | $0.385 | |
ETH | <0.01% | $1.28 | 0.2993 | $0.383 | |
ETH | <0.01% | $0.239163 | 1.5942 | $0.3812 | |
ETH | <0.01% | $0.012654 | 30.1058 | $0.3809 | |
ETH | <0.01% | $0.00586 | 64.9258 | $0.3804 | |
ETH | <0.01% | <$0.000001 | 730,872,527.5181 | $0.3788 | |
ETH | <0.01% | <$0.000001 | 4,207,857.7189 | $0.3775 | |
ETH | <0.01% | $0.002015 | 185.6373 | $0.3741 | |
ETH | <0.01% | $0.000673 | 555.5835 | $0.3736 | |
ETH | <0.01% | $0.102177 | 3.6481 | $0.3727 | |
ETH | <0.01% | $0.001204 | 306.3006 | $0.3689 | |
ETH | <0.01% | $0.305003 | 1.1996 | $0.3658 | |
ETH | <0.01% | <$0.000001 | 184,472,180.1981 | $0.3641 | |
ETH | <0.01% | $0.567206 | 0.641 | $0.3635 | |
ETH | <0.01% | $0.000023 | 15,929.6415 | $0.3611 | |
ETH | <0.01% | $69,979.04 | 0.00000514 | $0.3596 | |
ETH | <0.01% | $0.000679 | 528.6986 | $0.359 | |
ETH | <0.01% | $0.36629 | 0.9792 | $0.3586 | |
ETH | <0.01% | $0.276271 | 1.2977 | $0.3585 | |
ETH | <0.01% | $0.092171 | 3.8414 | $0.354 | |
ETH | <0.01% | $0.971745 | 0.3631 | $0.3528 | |
ETH | <0.01% | <$0.000001 | 3,005,280.3551 | $0.3522 | |
ETH | <0.01% | $0.041587 | 8.4654 | $0.352 | |
ETH | <0.01% | <$0.000001 | 2,344,099.4849 | $0.3447 | |
ETH | <0.01% | <$0.000001 | 736,033.2523 | $0.343 | |
ETH | <0.01% | $0.00632 | 54.1618 | $0.3423 | |
ETH | <0.01% | <$0.000001 | 113,160,008.7046 | $0.3385 | |
ETH | <0.01% | $0.706854 | 0.4772 | $0.3372 | |
ETH | <0.01% | $0.001998 | 168.6981 | $0.337 | |
ETH | <0.01% | $0.000333 | 1,009.0975 | $0.336 | |
ETH | <0.01% | $0.001581 | 211.9216 | $0.335 | |
ETH | <0.01% | $0.005898 | 56.5827 | $0.3337 | |
ETH | <0.01% | $592.83 | 0.00056283 | $0.3336 | |
ETH | <0.01% | $0.000177 | 1,880.7386 | $0.3325 | |
ETH | <0.01% | $0.166966 | 1.9863 | $0.3316 | |
ETH | <0.01% | <$0.000001 | 822,207,257.9739 | $0.3302 | |
ETH | <0.01% | $0.003974 | 82.8049 | $0.329 | |
ETH | <0.01% | $0.000825 | 396.7815 | $0.3275 | |
ETH | <0.01% | $0.017032 | 19.2131 | $0.3272 | |
ETH | <0.01% | $0.004433 | 73.7449 | $0.3269 | |
ETH | <0.01% | $0.000403 | 810.9442 | $0.3265 | |
ETH | <0.01% | $0.999448 | 0.3258 | $0.3256 | |
ETH | <0.01% | $0.032385 | 10.0346 | $0.3249 | |
ETH | <0.01% | $0.00015 | 2,162.4763 | $0.3247 | |
ETH | <0.01% | $0.189511 | 1.7035 | $0.3228 | |
ETH | <0.01% | $39.58 | 0.00813582 | $0.322 | |
ETH | <0.01% | $0.003451 | 92.9593 | $0.3208 | |
ETH | <0.01% | $0.007124 | 44.8623 | $0.3196 | |
ETH | <0.01% | $0.001002 | 318.3125 | $0.3189 | |
ETH | <0.01% | $43.35 | 0.00735163 | $0.3186 | |
ETH | <0.01% | $0.001054 | 301.1 | $0.3174 | |
ETH | <0.01% | $0.000021 | 14,952.5112 | $0.3168 | |
ETH | <0.01% | $0.000121 | 2,608.0052 | $0.316 | |
ETH | <0.01% | $0.108135 | 2.9014 | $0.3137 | |
ETH | <0.01% | $0.004188 | 74.4207 | $0.3116 | |
ETH | <0.01% | $0.203526 | 1.5305 | $0.3115 | |
ETH | <0.01% | $0.003569 | 86.8613 | $0.31 | |
ETH | <0.01% | $0.032357 | 9.5394 | $0.3086 | |
ETH | <0.01% | $0.018382 | 16.5756 | $0.3046 | |
ETH | <0.01% | $0.000471 | 644.46 | $0.3037 | |
ETH | <0.01% | $0.000832 | 364.3735 | $0.3032 | |
ETH | <0.01% | $0.000234 | 1,285.626 | $0.3009 | |
ETH | <0.01% | $0.027904 | 10.7795 | $0.3007 | |
ETH | <0.01% | $0.005228 | 57.2167 | $0.2991 | |
ETH | <0.01% | $0.000002 | 162,731.3672 | $0.2934 | |
ETH | <0.01% | $0.999895 | 0.2927 | $0.2926 | |
ETH | <0.01% | $0.007019 | 41.4669 | $0.291 | |
ETH | <0.01% | $0.212614 | 1.3595 | $0.289 | |
ETH | <0.01% | $0.056784 | 5.0694 | $0.2878 | |
ETH | <0.01% | $0.999965 | 0.2856 | $0.2855 | |
ETH | <0.01% | $0.030304 | 9.3751 | $0.2841 | |
ETH | <0.01% | $0.036951 | 7.6866 | $0.284 | |
ETH | <0.01% | $0.000049 | 5,787.6379 | $0.2822 | |
ETH | <0.01% | $0.003624 | 77.2909 | $0.28 | |
ETH | <0.01% | $0.001033 | 270.3361 | $0.2792 | |
ETH | <0.01% | $0.048209 | 5.7889 | $0.279 | |
ETH | <0.01% | $0.284762 | 0.9795 | $0.2789 | |
ETH | <0.01% | $0.002904 | 95.8156 | $0.2782 | |
ETH | <0.01% | $0.022795 | 12.1994 | $0.278 | |
ETH | <0.01% | <$0.000001 | 5,581,394.2699 | $0.2737 | |
ETH | <0.01% | <$0.000001 | 1,833,767.5936 | $0.2722 | |
ETH | <0.01% | $0.00016 | 1,702.4128 | $0.2716 | |
ETH | <0.01% | $0.141051 | 1.9236 | $0.2713 | |
ETH | <0.01% | $19.3 | 0.0141 | $0.2711 | |
ETH | <0.01% | $0.000306 | 883.606 | $0.2703 | |
ETH | <0.01% | $0.020295 | 13.316 | $0.2702 | |
ETH | <0.01% | $1.55 | 0.1737 | $0.2685 | |
ETH | <0.01% | <$0.000001 | 5,251,460.4164 | $0.2672 | |
ETH | <0.01% | $0.187268 | 1.424 | $0.2666 | |
ETH | <0.01% | $0.009216 | 28.7322 | $0.2647 | |
ETH | <0.01% | <$0.000001 | 11,827,892.7877 | $0.2642 | |
ETH | <0.01% | $0.000635 | 415.9816 | $0.2639 | |
ETH | <0.01% | $0.029433 | 8.9375 | $0.263 | |
ETH | <0.01% | $0.074451 | 3.5299 | $0.2628 | |
ETH | <0.01% | $0.020303 | 12.9424 | $0.2627 | |
ETH | <0.01% | $0.000372 | 702.5384 | $0.2614 | |
ETH | <0.01% | $0.000989 | 263.3076 | $0.2604 | |
ETH | <0.01% | $0.001491 | 172.8255 | $0.2577 | |
ETH | <0.01% | $0.041781 | 6.0867 | $0.2543 | |
ETH | <0.01% | $0.000175 | 1,455.3954 | $0.2542 | |
ETH | <0.01% | $0.00971 | 25.8143 | $0.2506 | |
ETH | <0.01% | <$0.000001 | 1,474,206.3627 | $0.2502 | |
ETH | <0.01% | $0.019662 | 12.6456 | $0.2486 | |
ETH | <0.01% | $0.406048 | 0.6074 | $0.2466 | |
ETH | <0.01% | $2.2 | 0.1117 | $0.2456 | |
ETH | <0.01% | $0.000691 | 354.8798 | $0.245 | |
ETH | <0.01% | $0.00211 | 115.3078 | $0.2432 | |
ETH | <0.01% | $0.000316 | 765.1941 | $0.242 | |
ETH | <0.01% | $0.002183 | 110.1418 | $0.2404 | |
ETH | <0.01% | $0.012025 | 19.9805 | $0.2402 | |
ETH | <0.01% | $1,703.31 | 0.00014032 | $0.239 | |
ETH | <0.01% | $0.004679 | 51.0407 | $0.2388 | |
ETH | <0.01% | <$0.000001 | 121,988,603.3383 | $0.236 | |
ETH | <0.01% | $2.44 | 0.0959 | $0.2338 | |
ETH | <0.01% | $0.00299 | 77.4205 | $0.2314 | |
ETH | <0.01% | $0.012653 | 18.2518 | $0.2309 | |
ETH | <0.01% | $0.015675 | 14.7299 | $0.2308 | |
ETH | <0.01% | $0.085788 | 2.6513 | $0.2274 | |
ETH | <0.01% | $0.000368 | 616.1023 | $0.2265 | |
ETH | <0.01% | <$0.000001 | 590,878.0194 | $0.2263 | |
ETH | <0.01% | $0.001312 | 171.752 | $0.2253 | |
ETH | <0.01% | $84.49 | 0.00266132 | $0.2248 | |
ETH | <0.01% | $0.000089 | 2,525.77 | $0.2245 | |
ETH | <0.01% | $0.019929 | 11.258 | $0.2243 | |
ETH | <0.01% | $0.01198 | 18.6692 | $0.2236 | |
ETH | <0.01% | $0.048856 | 4.5738 | $0.2234 | |
ETH | <0.01% | $0.00009 | 2,471.8211 | $0.2231 | |
ETH | <0.01% | $84,659 | 0.00000262 | $0.2214 | |
ETH | <0.01% | $0.000103 | 2,152.3881 | $0.2214 | |
ETH | <0.01% | <$0.000001 | 4,125,897.0325 | $0.2212 | |
ETH | <0.01% | $0.000032 | 7,000.0312 | $0.2211 | |
ETH | <0.01% | $0.000186 | 1,183.1333 | $0.2202 | |
ETH | <0.01% | $0.178015 | 1.2367 | $0.2201 | |
ETH | <0.01% | $0.000092 | 2,376.2898 | $0.2195 | |
ETH | <0.01% | $0.25605 | 0.8514 | $0.2179 | |
ETH | <0.01% | $0.000032 | 6,685.3206 | $0.2152 | |
ETH | <0.01% | $0.002433 | 87.7489 | $0.2135 | |
ETH | <0.01% | <$0.000001 | 19,801,915.9752 | $0.2092 | |
ETH | <0.01% | $0.000151 | 1,383.3956 | $0.2091 | |
ETH | <0.01% | $0.179996 | 1.1603 | $0.2088 | |
ETH | <0.01% | $2.66 | 0.0779 | $0.2069 | |
ETH | <0.01% | $0.000019 | 10,515.202 | $0.2049 | |
ETH | <0.01% | $0.000001 | 297,240.8898 | $0.2048 | |
ETH | <0.01% | <$0.000001 | 4,446,596.3035 | $0.204 | |
ETH | <0.01% | $0.00045 | 453.3154 | $0.204 | |
ETH | <0.01% | $0.000345 | 587.6766 | $0.2026 | |
ETH | <0.01% | <$0.000001 | 1,652,677,705.0624 | $0.2017 | |
ETH | <0.01% | $0.000266 | 756.9157 | $0.2013 | |
ETH | <0.01% | $0.043711 | 4.6024 | $0.2011 | |
ETH | <0.01% | $0.000093 | 2,146.2671 | $0.2005 | |
ETH | <0.01% | $0.000104 | 1,916.0609 | $0.1992 | |
ETH | <0.01% | $0.001776 | 111.6313 | $0.1982 | |
ETH | <0.01% | <$0.000001 | 1,479,311.6946 | $0.1977 | |
ETH | <0.01% | $0.001847 | 106.9175 | $0.1974 | |
ETH | <0.01% | <$0.000001 | 1,968,669,119.5028 | $0.1945 | |
ETH | <0.01% | <$0.000001 | 17,305,969.7973 | $0.1925 | |
ETH | <0.01% | $0.000099 | 1,941.3851 | $0.1921 | |
ETH | <0.01% | $0.002602 | 73.8264 | $0.192 | |
ETH | <0.01% | $0.006 | 31.9307 | $0.1915 | |
ETH | <0.01% | $0.000068 | 2,776.9495 | $0.1888 | |
ETH | <0.01% | $0.174982 | 1.0726 | $0.1876 | |
ETH | <0.01% | $0.003809 | 48.8652 | $0.1861 | |
ETH | <0.01% | $5.89 | 0.0307 | $0.181 | |
ETH | <0.01% | $0.000315 | 573.0915 | $0.1803 | |
ETH | <0.01% | $0.169121 | 1.0645 | $0.18 | |
ETH | <0.01% | $0.004775 | 37.6836 | $0.1799 | |
ETH | <0.01% | $0.002145 | 82.9707 | $0.1779 | |
ETH | <0.01% | $0.000267 | 665.7975 | $0.1777 | |
ETH | <0.01% | $0.003 | 59.0047 | $0.177 | |
ETH | <0.01% | $0.000039 | 4,524.6403 | $0.1769 | |
ETH | <0.01% | $0.00047 | 375.2483 | $0.1763 | |
ETH | <0.01% | $0.000044 | 3,998.8516 | $0.1763 | |
ETH | <0.01% | $0.000102 | 1,729.1057 | $0.1761 | |
ETH | <0.01% | $0.000188 | 938.7987 | $0.1761 | |
ETH | <0.01% | $0.000967 | 182.1828 | $0.1761 | |
ETH | <0.01% | $12.71 | 0.0136 | $0.173 | |
ETH | <0.01% | $0.99823 | 0.1726 | $0.1722 | |
ETH | <0.01% | $0.093126 | 1.8312 | $0.1705 | |
ETH | <0.01% | $3,526.89 | 0.00004826 | $0.1701 | |
ETH | <0.01% | $0.000154 | 1,104.5164 | $0.17 | |
ETH | <0.01% | $0.000428 | 396.471 | $0.1697 | |
ETH | <0.01% | $0.026374 | 6.3857 | $0.1684 | |
ETH | <0.01% | $0.02623 | 6.4105 | $0.1681 | |
ETH | <0.01% | $0.173997 | 0.9586 | $0.1668 | |
ETH | <0.01% | $0.873012 | 0.191 | $0.1667 | |
ETH | <0.01% | $138.81 | 0.00119534 | $0.1659 | |
ETH | <0.01% | $0.006432 | 25.3622 | $0.1631 | |
ETH | <0.01% | $0.062661 | 2.5928 | $0.1624 | |
ETH | <0.01% | $0.024741 | 6.4934 | $0.1606 | |
ETH | <0.01% | $0.0001 | 1,599.1008 | $0.1602 | |
ETH | <0.01% | $0.000847 | 188.8554 | $0.16 | |
ETH | <0.01% | $3.94 | 0.0405 | $0.1596 | |
ETH | <0.01% | $0.001049 | 151.793 | $0.1592 | |
ETH | <0.01% | $0.643776 | 0.2467 | $0.1588 | |
ETH | <0.01% | $0.009264 | 17.1268 | $0.1586 | |
ETH | <0.01% | $0.12916 | 1.2271 | $0.1584 | |
ETH | <0.01% | $1.66 | 0.0942 | $0.1563 | |
ETH | <0.01% | $0.000038 | 4,065.3885 | $0.1559 | |
ETH | <0.01% | $0.069113 | 2.2567 | $0.1559 | |
ETH | <0.01% | $0.001516 | 102.4187 | $0.1552 | |
ETH | <0.01% | <$0.000001 | 271,062,761.8044 | $0.1543 | |
ETH | <0.01% | $0.007135 | 21.5694 | $0.1538 | |
ETH | <0.01% | $0.525555 | 0.2924 | $0.1536 | |
ETH | <0.01% | <$0.000001 | 1,570,253.6481 | $0.1515 | |
ETH | <0.01% | $0.009771 | 15.2561 | $0.149 | |
ETH | <0.01% | $0.046519 | 3.2038 | $0.149 | |
ETH | <0.01% | $0.000218 | 683.6438 | $0.1489 | |
ETH | <0.01% | $0.000204 | 728.86 | $0.1488 | |
ETH | <0.01% | $0.002001 | 73.7144 | $0.1475 | |
ETH | <0.01% | $0.008391 | 17.5826 | $0.1475 | |
ETH | <0.01% | $0.008363 | 17.5538 | $0.1468 | |
ETH | <0.01% | <$0.000001 | 2,671,603.4582 | $0.1462 | |
ETH | <0.01% | $0.005471 | 26.6388 | $0.1457 | |
ETH | <0.01% | $0.005089 | 28.6117 | $0.1456 | |
ETH | <0.01% | <$0.000001 | 884,938.949 | $0.1455 | |
ETH | <0.01% | $0.01798 | 8.081 | $0.1452 | |
ETH | <0.01% | <$0.000001 | 637,388.9803 | $0.145 | |
ETH | <0.01% | $0.000041 | 3,550.0048 | $0.1449 | |
ETH | <0.01% | $0.000109 | 1,331.5863 | $0.1445 | |
ETH | <0.01% | $0.022868 | 6.3117 | $0.1443 | |
ETH | <0.01% | $0.357979 | 0.3964 | $0.1419 | |
ETH | <0.01% | $0.521008 | 0.2713 | $0.1413 | |
ETH | <0.01% | <$0.000001 | 1,594,597,669.6127 | $0.1408 | |
ETH | <0.01% | $0.002528 | 55.444 | $0.1401 | |
ETH | <0.01% | $0.050378 | 2.7649 | $0.1392 | |
ETH | <0.01% | <$0.000001 | 166,646,816.575 | $0.1389 | |
ETH | <0.01% | $0.000343 | 403.9155 | $0.1387 | |
ETH | <0.01% | <$0.000001 | 1,932,005,632.2739 | $0.1374 | |
ETH | <0.01% | <$0.000001 | 1,894,870.6405 | $0.1367 | |
ETH | <0.01% | $0.00058 | 235.8574 | $0.1367 | |
ETH | <0.01% | $0.057961 | 2.3542 | $0.1364 | |
ETH | <0.01% | $0.001483 | 91.7833 | $0.1361 | |
ETH | <0.01% | <$0.000001 | 300,775.6954 | $0.1346 | |
ETH | <0.01% | $0.000116 | 1,161.5746 | $0.1342 | |
ETH | <0.01% | <$0.000001 | 577,750.7248 | $0.1332 | |
ETH | <0.01% | <$0.000001 | 1,484,310.8143 | $0.1327 | |
ETH | <0.01% | $0.029008 | 4.5665 | $0.1324 | |
ETH | <0.01% | $1.09 | 0.1211 | $0.132 | |
ETH | <0.01% | $0.000021 | 6,354.7777 | $0.1314 | |
ETH | <0.01% | $0.000009 | 14,303.7615 | $0.1313 | |
ETH | <0.01% | $0.000046 | 2,853.2477 | $0.1313 | |
ETH | <0.01% | $0.084329 | 1.5544 | $0.131 | |
ETH | <0.01% | $0.052385 | 2.4746 | $0.1296 | |
ETH | <0.01% | $0.000007 | 18,811.9206 | $0.1295 | |
ETH | <0.01% | $0.009262 | 13.9545 | $0.1292 | |
ETH | <0.01% | $0.000174 | 740.7753 | $0.1292 | |
ETH | <0.01% | <$0.000001 | 26,930,133.6475 | $0.1285 | |
ETH | <0.01% | $0.804835 | 0.1588 | $0.1277 | |
ETH | <0.01% | $1,597.71 | 0.00007943 | $0.1269 | |
ETH | <0.01% | $0.499322 | 0.2533 | $0.1264 | |
ETH | <0.01% | $0.027126 | 4.6212 | $0.1253 | |
ETH | <0.01% | $0.000833 | 150.1643 | $0.1251 | |
ETH | <0.01% | $1.17 | 0.1066 | $0.1247 | |
ETH | <0.01% | $0.000102 | 1,211.9714 | $0.1234 | |
ETH | <0.01% | $0.001933 | 63.84 | $0.1233 | |
ETH | <0.01% | <$0.000001 | 1,438,440.2688 | $0.122 | |
ETH | <0.01% | $0.000326 | 374.2369 | $0.1219 | |
ETH | <0.01% | <$0.000001 | 474,487.907 | $0.1218 | |
ETH | <0.01% | $0.087583 | 1.379 | $0.1207 | |
ETH | <0.01% | $0.000109 | 1,106.3958 | $0.1207 | |
ETH | <0.01% | <$0.000001 | 38,575,321.4789 | $0.1196 | |
ETH | <0.01% | $0.000123 | 972.2392 | $0.1194 | |
ETH | <0.01% | $0.000169 | 707.4541 | $0.1194 | |
ETH | <0.01% | $0.011898 | 10.0262 | $0.1192 | |
ETH | <0.01% | $0.000247 | 482.8329 | $0.1192 | |
ETH | <0.01% | <$0.000001 | 343,177,771.2804 | $0.1183 | |
ETH | <0.01% | $0.000749 | 157.4035 | $0.1179 | |
ETH | <0.01% | $0.000467 | 250.4733 | $0.117 | |
ETH | <0.01% | $0.005116 | 22.852 | $0.1169 | |
ETH | <0.01% | $0.028123 | 4.1482 | $0.1166 | |
ETH | <0.01% | $0.005231 | 22.0413 | $0.1153 | |
ETH | <0.01% | <$0.000001 | 553,329.3422 | $0.1144 | |
ETH | <0.01% | $0.028415 | 4.0213 | $0.1142 | |
ETH | <0.01% | $0.000307 | 371.3679 | $0.114 | |
ETH | <0.01% | $1,360.84 | 0.00008334 | $0.1134 | |
ETH | <0.01% | $0.076033 | 1.4903 | $0.1133 | |
ETH | <0.01% | $2.82 | 0.0401 | $0.113 | |
ETH | <0.01% | $0.000448 | 251.4043 | $0.1126 | |
ETH | <0.01% | $0.014169 | 7.8751 | $0.1115 | |
ETH | <0.01% | $0.018387 | 6.0688 | $0.1115 | |
ETH | <0.01% | $0.000017 | 6,564.9978 | $0.1112 | |
ETH | <0.01% | $0.000501 | 221.2873 | $0.1109 | |
ETH | <0.01% | $0.00053 | 207.8076 | $0.1101 | |
ETH | <0.01% | $0.005465 | 20.0185 | $0.1094 | |
ETH | <0.01% | $0.123729 | 0.8829 | $0.1092 | |
ETH | <0.01% | <$0.000001 | 2,670,322.4852 | $0.1083 | |
ETH | <0.01% | $0.122436 | 0.8833 | $0.1081 | |
ETH | <0.01% | $0.00139 | 77.5792 | $0.1078 | |
ETH | <0.01% | $0.113023 | 0.9506 | $0.1074 | |
ETH | <0.01% | $0.618283 | 0.1733 | $0.1071 | |
ETH | <0.01% | $0.002024 | 52.6803 | $0.1066 | |
ETH | <0.01% | <$0.000001 | 303,383.8346 | $0.1065 | |
ETH | <0.01% | $0.029529 | 3.6037 | $0.1064 | |
ETH | <0.01% | $0.014499 | 7.2492 | $0.1051 | |
ETH | <0.01% | $0.000479 | 218.9717 | $0.1048 | |
ETH | <0.01% | $0.01745 | 5.9508 | $0.1038 | |
ETH | <0.01% | $0.003723 | 27.7553 | $0.1033 | |
ETH | <0.01% | $0.000088 | 1,162.5131 | $0.1022 | |
ETH | <0.01% | $0.000372 | 273.7092 | $0.1019 | |
ETH | <0.01% | <$0.000001 | 168,600,789.2145 | $0.1008 | |
ETH | <0.01% | $0.00036 | 278.529 | $0.1003 | |
AVAX | 0.21% | $0.000004 | 7,273,103.5705 | $26.55 | |
AVAX | 0.05% | $3.16 | 2.0704 | $6.54 | |
AVAX | 0.01% | $0.00007 | 23,231.0612 | $1.63 | |
AVAX | <0.01% | $1.14 | 0.7985 | $0.9092 | |
AVAX | <0.01% | $0.000001 | 1,425,184.093 | $0.8679 | |
AVAX | <0.01% | $19.33 | 0.0361 | $0.697552 | |
AVAX | <0.01% | $0.377198 | 1.6328 | $0.6159 | |
AVAX | <0.01% | $0.235294 | 2.4947 | $0.5869 | |
AVAX | <0.01% | $0.000005 | 108,963.2688 | $0.5132 | |
AVAX | <0.01% | $140.04 | 0.00365613 | $0.512 | |
AVAX | <0.01% | $0.999784 | 0.4668 | $0.4667 | |
AVAX | <0.01% | $15.55 | 0.0284 | $0.4414 | |
AVAX | <0.01% | $12.79 | 0.034 | $0.4353 | |
AVAX | <0.01% | $23.19 | 0.0185 | $0.4283 | |
AVAX | <0.01% | <$0.000001 | 59,151,797.9885 | $0.4022 | |
AVAX | <0.01% | $0.99998 | 0.3752 | $0.3751 | |
AVAX | <0.01% | $0.004158 | 84.496 | $0.3513 | |
AVAX | <0.01% | $0.000001 | 217,828.4583 | $0.2635 | |
AVAX | <0.01% | $0.008079 | 28.7417 | $0.2322 | |
AVAX | <0.01% | $84,977.28 | 0.00000272 | $0.2311 | |
AVAX | <0.01% | $0.085678 | 2.6921 | $0.2306 | |
AVAX | <0.01% | $140.14 | 0.00154367 | $0.2163 | |
AVAX | <0.01% | $0.000533 | 395.7172 | $0.2109 | |
AVAX | <0.01% | $0.000119 | 1,516.5437 | $0.1799 | |
AVAX | <0.01% | $85,082 | 0.00000173 | $0.1471 | |
AVAX | <0.01% | $0.999891 | 0.1319 | $0.1318 | |
BASE | <0.01% | $0.026045 | 34.9921 | $0.9113 | |
BASE | <0.01% | $0.001082 | 798.3456 | $0.8638 | |
BASE | <0.01% | $0.415156 | 2.0185 | $0.8379 | |
BASE | <0.01% | $0.087771 | 9.5233 | $0.8358 | |
BASE | <0.01% | $1.14 | 0.7039 | $0.8024 | |
BASE | <0.01% | $0.066597 | 11.4995 | $0.7658 | |
BASE | <0.01% | $0.000032 | 22,851.0691 | $0.7323 | |
BASE | <0.01% | $0.020625 | 34.8456 | $0.7187 | |
BASE | <0.01% | $0.193927 | 3.5877 | $0.6957 | |
BASE | <0.01% | $0.006234 | 109.2217 | $0.6808 | |
BASE | <0.01% | $85,049 | 0.00000794 | $0.6752 | |
BASE | <0.01% | $0.000304 | 2,182.964 | $0.6631 | |
BASE | <0.01% | $0.000161 | 4,096.4436 | $0.6601 | |
BASE | <0.01% | $35 | 0.0188 | $0.6565 | |
BASE | <0.01% | $0.000466 | 1,385.8342 | $0.6457 | |
BASE | <0.01% | $0.004432 | 143.4494 | $0.6357 | |
BASE | <0.01% | $84,838 | 0.00000729 | $0.6184 | |
BASE | <0.01% | $0.000016 | 39,455.2684 | $0.6166 | |
BASE | <0.01% | <$0.000001 | 16,787,772.5526 | $0.606 | |
BASE | <0.01% | $1,675.55 | 0.00036085 | $0.6046 | |
BASE | <0.01% | $0.000008 | 71,050 | $0.5973 | |
BASE | <0.01% | $0.015985 | 36.4712 | $0.583 | |
BASE | <0.01% | <$0.000001 | 36,948,197.1446 | $0.5763 | |
BASE | <0.01% | $2.45 | 0.2345 | $0.5744 | |
BASE | <0.01% | $0.009136 | 60.4366 | $0.5521 | |
BASE | <0.01% | $0.029374 | 18.3344 | $0.5385 | |
BASE | <0.01% | $0.174359 | 3.0492 | $0.5316 | |
BASE | <0.01% | $0.046103 | 11.3259 | $0.5221 | |
BASE | <0.01% | $84,850 | 0.00000608 | $0.5158 | |
BASE | <0.01% | $0.000071 | 7,224.0902 | $0.5129 | |
BASE | <0.01% | $0.99998 | 0.495 | $0.495 | |
BASE | <0.01% | $0.006722 | 72.9336 | $0.4902 | |
BASE | <0.01% | $0.01469 | 33.302 | $0.4891 | |
BASE | <0.01% | $0.002669 | 180.627 | $0.482 | |
BASE | <0.01% | $1,923.37 | 0.00024728 | $0.4756 | |
BASE | <0.01% | $0.998657 | 0.4732 | $0.4725 | |
BASE | <0.01% | $0.078202 | 5.8315 | $0.456 | |
BASE | <0.01% | $0.020982 | 21.094 | $0.4426 | |
BASE | <0.01% | $0.00747 | 58.318 | $0.4356 | |
BASE | <0.01% | $0.000109 | 3,974.3977 | $0.4315 | |
BASE | <0.01% | $0.003811 | 106.3348 | $0.4052 | |
BASE | <0.01% | $1 | 0.4012 | $0.4012 | |
BASE | <0.01% | $0.000032 | 12,451.1273 | $0.401 | |
BASE | <0.01% | $0.000002 | 192,970.2659 | $0.3897 | |
BASE | <0.01% | $2.15 | 0.1799 | $0.3868 | |
BASE | <0.01% | $0.052863 | 7.2061 | $0.3809 | |
BASE | <0.01% | $4,551.03 | 0.0000837 | $0.3809 | |
BASE | <0.01% | $3.16 | 0.1172 | $0.3702 | |
BASE | <0.01% | $0.010393 | 34.759 | $0.3612 | |
BASE | <0.01% | $0.000133 | 2,712.5183 | $0.3608 | |
BASE | <0.01% | $0.000834 | 430.128 | $0.3586 | |
BASE | <0.01% | $0.00017 | 2,077.2849 | $0.3538 | |
BASE | <0.01% | $0.000011 | 31,073.8606 | $0.3486 | |
BASE | <0.01% | $0.441779 | 0.7864 | $0.3474 | |
BASE | <0.01% | $0.000367 | 941.4324 | $0.3459 | |
BASE | <0.01% | $1.35 | 0.2493 | $0.3365 | |
BASE | <0.01% | $0.002619 | 119.4044 | $0.3127 | |
BASE | <0.01% | $0.998187 | 0.3128 | $0.3122 | |
BASE | <0.01% | $0.275924 | 1.1152 | $0.3077 | |
BASE | <0.01% | $0.021838 | 14.0441 | $0.3066 | |
BASE | <0.01% | $0.000486 | 630.9078 | $0.3064 | |
BASE | <0.01% | $0.577674 | 0.5121 | $0.2958 | |
BASE | <0.01% | $0.01591 | 18 | $0.2863 | |
BASE | <0.01% | $0.000233 | 1,219.1488 | $0.2835 | |
BASE | <0.01% | $0.000515 | 550.0998 | $0.2832 | |
BASE | <0.01% | $2.18 | 0.1259 | $0.2744 | |
BASE | <0.01% | $174.35 | 0.0015324 | $0.2671 | |
BASE | <0.01% | $0.001221 | 215.8007 | $0.2634 | |
BASE | <0.01% | $0.00167 | 152.2065 | $0.2542 | |
BASE | <0.01% | $0.007902 | 32.0507 | $0.2532 | |
BASE | <0.01% | $0.226152 | 1.1152 | $0.2522 | |
BASE | <0.01% | $0.052904 | 4.7568 | $0.2516 | |
BASE | <0.01% | $0.076315 | 3.1576 | $0.2409 | |
BASE | <0.01% | $0.000005 | 43,049.7401 | $0.2341 | |
BASE | <0.01% | $0.03621 | 6.3441 | $0.2297 | |
BASE | <0.01% | $0.019299 | 11.3784 | $0.2195 | |
BASE | <0.01% | $0.000609 | 353.2236 | $0.215 | |
BASE | <0.01% | $2.92 | 0.0722 | $0.2107 | |
BASE | <0.01% | $0.175078 | 1.1526 | $0.2018 | |
BASE | <0.01% | $0.389541 | 0.5088 | $0.1982 | |
BASE | <0.01% | $0.310289 | 0.6285 | $0.195 | |
BASE | <0.01% | $0.000005 | 38,037.2567 | $0.1939 | |
BASE | <0.01% | $0.000359 | 532.4497 | $0.1911 | |
BASE | <0.01% | $0.249978 | 0.7616 | $0.1903 | |
BASE | <0.01% | $0.051072 | 3.707 | $0.1893 | |
BASE | <0.01% | $1.05 | 0.1788 | $0.1874 | |
BASE | <0.01% | $1,602.64 | 0.00011242 | $0.1801 | |
BASE | <0.01% | $0.001424 | 124.0847 | $0.1767 | |
BASE | <0.01% | $0.002713 | 64.1156 | $0.1739 | |
BASE | <0.01% | $0.000777 | 223.3582 | $0.1735 | |
BASE | <0.01% | $0.000888 | 194.6655 | $0.1728 | |
BASE | <0.01% | $0.00397 | 42.5118 | $0.1687 | |
BASE | <0.01% | $0.000004 | 37,185.0523 | $0.1658 | |
BASE | <0.01% | $0.000003 | 48,075.7151 | $0.1605 | |
BASE | <0.01% | $0.050358 | 3.0858 | $0.1553 | |
BASE | <0.01% | $0.073899 | 2.0659 | $0.1526 | |
BASE | <0.01% | $0.997752 | 0.1424 | $0.142 | |
BASE | <0.01% | $0.449487 | 0.3106 | $0.1396 | |
BASE | <0.01% | $0.010917 | 12.3357 | $0.1346 | |
BASE | <0.01% | $0.000153 | 852.7317 | $0.1308 | |
BASE | <0.01% | $0.001164 | 111.866 | $0.1301 | |
BASE | <0.01% | $0.04162 | 3.0588 | $0.1273 | |
BASE | <0.01% | $0.000009 | 14,177.7886 | $0.124 | |
BASE | <0.01% | $1,601.6 | 0.00007739 | $0.1239 | |
BASE | <0.01% | $0.240018 | 0.4797 | $0.1151 | |
BASE | <0.01% | $0.011902 | 9.115 | $0.1084 | |
BASE | <0.01% | $0.999976 | 0.1071 | $0.107 | |
BASE | <0.01% | $0.000011 | 9,645.359 | $0.1066 | |
BASE | <0.01% | $1,605.07 | 0.00006489 | $0.104146 | |
BASE | <0.01% | $0.734055 | 0.1382 | $0.1014 | |
POL | 0.01% | $0.99998 | 1.3171 | $1.32 | |
POL | <0.01% | $1.37 | 0.726 | $0.9945 | |
POL | <0.01% | $0.189928 | 4.6829 | $0.889403 | |
POL | <0.01% | $0.016169 | 54.7556 | $0.8853 | |
POL | <0.01% | $0.999264 | 0.8691 | $0.8685 | |
POL | <0.01% | $0.206783 | 4.1509 | $0.8583 | |
POL | <0.01% | $0.171019 | 4.8461 | $0.8287 | |
POL | <0.01% | $85,026 | 0.00000947 | $0.8051 | |
POL | <0.01% | $5.26 | 0.1507 | $0.7927 | |
POL | <0.01% | $0.99998 | 0.7861 | $0.786 | |
POL | <0.01% | $0.146623 | 5.1853 | $0.7602 | |
POL | <0.01% | $85,058 | 0.00000884 | $0.7519 | |
POL | <0.01% | <$0.000001 | 69,842,426.6516 | $0.7403 | |
POL | <0.01% | $0.001628 | 453.3062 | $0.7379 | |
POL | <0.01% | $0.01846 | 39.0193 | $0.7202 | |
POL | <0.01% | $0.99997 | 0.7006 | $0.7005 | |
POL | <0.01% | $0.019343 | 35.6898 | $0.6903 | |
POL | <0.01% | $0.006059 | 110.1459 | $0.6673 | |
POL | <0.01% | $0.013727 | 46.6451 | $0.6402 | |
POL | <0.01% | $0.000414 | 1,535.0329 | $0.6348 | |
POL | <0.01% | $0.000002 | 293,437.7019 | $0.6311 | |
POL | <0.01% | $0.189814 | 3.0714 | $0.5829 | |
POL | <0.01% | $0.000008 | 68,250 | $0.5737 | |
POL | <0.01% | $1.11 | 0.51 | $0.5661 | |
POL | <0.01% | <$0.000001 | 4,166,738.8558 | $0.5341 | |
POL | <0.01% | $140.14 | 0.0037089 | $0.5197 | |
POL | <0.01% | $12.8 | 0.0394 | $0.5044 | |
POL | <0.01% | $0.283654 | 1.766 | $0.5009 | |
POL | <0.01% | $0.000271 | 1,834.4182 | $0.4966 | |
POL | <0.01% | $139.84 | 0.00338353 | $0.4731 | |
POL | <0.01% | $39.68 | 0.0119 | $0.4728 | |
POL | <0.01% | $3.98 | 0.1173 | $0.4669 | |
POL | <0.01% | $1.15 | 0.4032 | $0.4636 | |
POL | <0.01% | $0.062523 | 7.3639 | $0.4604 | |
POL | <0.01% | $0.277727 | 1.5499 | $0.4304 | |
POL | <0.01% | $0.000296 | 1,407.8848 | $0.4166 | |
POL | <0.01% | $0.276116 | 1.5082 | $0.4164 | |
POL | <0.01% | $0.24812 | 1.6774 | $0.4161 | |
POL | <0.01% | $0.006442 | 63.9464 | $0.4119 | |
POL | <0.01% | $0.102734 | 3.888 | $0.3994 | |
POL | <0.01% | $0.0023 | 169.4879 | $0.3897 | |
POL | <0.01% | $3,349.25 | 0.00011154 | $0.3735 | |
POL | <0.01% | $1,601.75 | 0.00023278 | $0.3728 | |
POL | <0.01% | $1 | 0.3714 | $0.3714 | |
POL | <0.01% | $0.042511 | 8.2289 | $0.3498 | |
POL | <0.01% | $0.003636 | 94.8341 | $0.3448 | |
POL | <0.01% | $0.032799 | 10.3684 | $0.34 | |
POL | <0.01% | $0.014449 | 22.9913 | $0.3321 | |
POL | <0.01% | $0.012145 | 26.7725 | $0.3251 | |
POL | <0.01% | $0.080303 | 3.9882 | $0.3202 | |
POL | <0.01% | $0.430107 | 0.7203 | $0.3098 | |
POL | <0.01% | $0.000409 | 702.1481 | $0.2875 | |
POL | <0.01% | $0.424037 | 0.6228 | $0.2641 | |
POL | <0.01% | $0.000743 | 337.5091 | $0.2507 | |
POL | <0.01% | $2.45 | 0.1019 | $0.2496 | |
POL | <0.01% | $0.196784 | 1.2512 | $0.2462 | |
POL | <0.01% | $19.27 | 0.012 | $0.2318 | |
POL | <0.01% | $0.000185 | 1,244.4423 | $0.2308 | |
POL | <0.01% | $0.001653 | 138.4206 | $0.2288 | |
POL | <0.01% | $0.000243 | 899.2751 | $0.2181 | |
POL | <0.01% | $0.012327 | 17.622 | $0.2172 | |
POL | <0.01% | $1,923.38 | 0.00011152 | $0.2144 | |
POL | <0.01% | $0.000805 | 259.4684 | $0.2089 | |
POL | <0.01% | $1,602.64 | 0.00012987 | $0.2081 | |
POL | <0.01% | $1,361.54 | 0.00015009 | $0.2043 | |
POL | <0.01% | <$0.000001 | 36,537,456.422 | $0.2009 | |
POL | <0.01% | $0.036348 | 5.3498 | $0.1944 | |
POL | <0.01% | $0.00045 | 418.119 | $0.1882 | |
POL | <0.01% | $1 | 0.1845 | $0.1844 | |
POL | <0.01% | $0.00137 | 131.8589 | $0.1806 | |
POL | <0.01% | $0.000085 | 2,037.5734 | $0.174 | |
POL | <0.01% | $12.79 | 0.0136 | $0.174 | |
POL | <0.01% | $0.568976 | 0.3014 | $0.1714 | |
POL | <0.01% | $0.220986 | 0.7721 | $0.1706 | |
POL | <0.01% | $0.000194 | 879.2289 | $0.1703 | |
POL | <0.01% | $0.001661 | 98.2865 | $0.1632 | |
POL | <0.01% | $0.039143 | 4.1101 | $0.1608 | |
POL | <0.01% | $0.009108 | 16.5577 | $0.1508 | |
POL | <0.01% | $0.0005 | 297.7909 | $0.1488 | |
POL | <0.01% | $1.05 | 0.1399 | $0.1465 | |
POL | <0.01% | $0.171712 | 0.8201 | $0.1408 | |
POL | <0.01% | $0.000874 | 153.2046 | $0.1339 | |
POL | <0.01% | $0.002176 | 58.4762 | $0.1272 | |
POL | <0.01% | $0.000173 | 720.0175 | $0.1249 | |
POL | <0.01% | $0.006702 | 17.9118 | $0.12 | |
POL | <0.01% | $0.000281 | 403.4996 | $0.1135 | |
POL | <0.01% | $0.009979 | 10.3816 | $0.1035 | |
POL | <0.01% | $0.008162 | 12.638 | $0.1031 | |
POL | <0.01% | $0.071996 | 1.4273 | $0.1027 | |
POL | <0.01% | $0.216787 | 0.4733 | $0.1026 | |
POL | <0.01% | $0.0739 | 1.3642 | $0.1008 | |
ZKEVM | 0.06% | $0.189985 | 36.5497 | $6.94 | |
ZKEVM | 0.05% | $0.999891 | 5.9393 | $5.94 | |
ZKEVM | 0.04% | $0.999966 | 5.5855 | $5.59 | |
ZKEVM | 0.04% | $1,604.69 | 0.00344652 | $5.53 | |
ZKEVM | 0.02% | $85,116 | 0.00002235 | $1.9 | |
ZKEVM | <0.01% | $1,604.51 | 0.00070649 | $1.13 | |
ZKEVM | <0.01% | $140.04 | 0.00773941 | $1.08 | |
ZKEVM | <0.01% | $0.999891 | 0.7245 | $0.7244 | |
ZKEVM | <0.01% | $1 | 0.6127 | $0.6127 | |
ARB | 0.01% | $0.99998 | 1.4225 | $1.42 | |
ARB | <0.01% | $1,920.72 | 0.00047116 | $0.9049 | |
ARB | <0.01% | $0.568688 | 1.5169 | $0.8626 | |
ARB | <0.01% | $0.99996 | 0.8063 | $0.8062 | |
ARB | <0.01% | $1,758.08 | 0.00045729 | $0.8039 | |
ARB | <0.01% | $85,048 | 0.00000935 | $0.7951 | |
ARB | <0.01% | $3.99 | 0.1918 | $0.7653 | |
ARB | <0.01% | $0.923723 | 0.8108 | $0.7489 | |
ARB | <0.01% | $1.4 | 0.4862 | $0.6806 | |
ARB | <0.01% | $0.009651 | 70.326 | $0.6787 | |
ARB | <0.01% | $1 | 0.6497 | $0.6503 | |
ARB | <0.01% | $1,804.58 | 0.00033306 | $0.601 | |
ARB | <0.01% | $0.077349 | 7.6415 | $0.591 | |
ARB | <0.01% | $85,098 | 0.00000663 | $0.5641 | |
ARB | <0.01% | $0.000012 | 45,056.9326 | $0.5496 | |
ARB | <0.01% | $0.031576 | 16.9878 | $0.5363 | |
ARB | <0.01% | $140.14 | 0.00382701 | $0.5363 | |
ARB | <0.01% | $6.46 | 0.0814 | $0.5258 | |
ARB | <0.01% | $0.044137 | 11.8381 | $0.5224 | |
ARB | <0.01% | $0.002825 | 182.481 | $0.5154 | |
ARB | <0.01% | $22.79 | 0.0218 | $0.496 | |
ARB | <0.01% | $0.441449 | 1.1114 | $0.4906 | |
ARB | <0.01% | $1,605.09 | 0.00029301 | $0.470308 | |
ARB | <0.01% | $0.56877 | 0.8155 | $0.4638 | |
ARB | <0.01% | $0.027482 | 16.8143 | $0.462 | |
ARB | <0.01% | $0.096822 | 4.5966 | $0.445 | |
ARB | <0.01% | $0.006756 | 64.505 | $0.4357 | |
ARB | <0.01% | $12.8 | 0.0331 | $0.423 | |
ARB | <0.01% | $83,895 | 0.00000485 | $0.4069 | |
ARB | <0.01% | $43.87 | 0.00901359 | $0.3954 | |
ARB | <0.01% | $0.99998 | 0.3819 | $0.3818 | |
ARB | <0.01% | $0.001328 | 275.5771 | $0.366 | |
ARB | <0.01% | $0.606651 | 0.5998 | $0.3638 | |
ARB | <0.01% | $84,935 | 0.00000414 | $0.3516 | |
ARB | <0.01% | $0.000007 | 46,978.0303 | $0.3424 | |
ARB | <0.01% | $0.999479 | 0.3329 | $0.3327 | |
ARB | <0.01% | $0.294247 | 1.0764 | $0.3167 | |
ARB | <0.01% | $0.058152 | 5.1979 | $0.3022 | |
ARB | <0.01% | $1.15 | 0.2565 | $0.295 | |
ARB | <0.01% | $84,850 | 0.00000315 | $0.2672 | |
ARB | <0.01% | $0.098713 | 2.507 | $0.2474 | |
ARB | <0.01% | $0.001424 | 152.5814 | $0.2173 | |
ARB | <0.01% | $0.044223 | 4.8499 | $0.2144 | |
ARB | <0.01% | $0.01881 | 10.6252 | $0.1998 | |
ARB | <0.01% | $0.999716 | 0.1905 | $0.1904 | |
ARB | <0.01% | $0.162265 | 1.1069 | $0.1796 | |
ARB | <0.01% | $0.071086 | 2.5144 | $0.1787 | |
ARB | <0.01% | $0.007064 | 25.2669 | $0.1784 | |
ARB | <0.01% | $1,601.6 | 0.000111 | $0.1777 | |
ARB | <0.01% | $0.02582 | 6.8112 | $0.1758 | |
ARB | <0.01% | $0.027781 | 6.3183 | $0.1755 | |
ARB | <0.01% | $1.07 | 0.1602 | $0.172 | |
ARB | <0.01% | $0.192718 | 0.862 | $0.1661 | |
ARB | <0.01% | $0.267073 | 0.5928 | $0.1583 | |
ARB | <0.01% | $0.968064 | 0.1602 | $0.155 | |
ARB | <0.01% | $0.007535 | 20.5254 | $0.1546 | |
ARB | <0.01% | $1.75 | 0.0859 | $0.1502 | |
ARB | <0.01% | $0.013582 | 10.7488 | $0.1459 | |
ARB | <0.01% | $0.909406 | 0.148 | $0.1345 | |
ARB | <0.01% | $0.58989 | 0.2231 | $0.1316 | |
ARB | <0.01% | $0.000565 | 228.9662 | $0.1292 | |
ARB | <0.01% | $0.161265 | 0.784 | $0.1264 | |
ARB | <0.01% | $0.012009 | 10.4458 | $0.1254 | |
ARB | <0.01% | $0.117933 | 1.0477 | $0.1235 | |
ARB | <0.01% | $1,606.3 | 0.00007466 | $0.1199 | |
ARB | <0.01% | $5.26 | 0.0224 | $0.1176 | |
ARB | <0.01% | $1.37 | 0.0837 | $0.1146 | |
ARB | <0.01% | $0.012975 | 8.7395 | $0.1133 | |
ARB | <0.01% | $0.024256 | 4.3259 | $0.1049 | |
ARB | <0.01% | $0.000011 | 9,093.1429 | $0.1014 | |
ARB | <0.01% | $3.16 | 0.032 | $0.1011 | |
ARB | <0.01% | $0.079325 | 1.2749 | $0.1011 | |
ARB | <0.01% | $0.002283 | 44.0613 | $0.1005 | |
ARB | <0.01% | $0.036659 | 2.7435 | $0.1005 | |
OP | <0.01% | $1,925.39 | 0.00051571 | $0.9929 | |
OP | <0.01% | $1 | 0.9425 | $0.9425 | |
OP | <0.01% | $1 | 0.9153 | $0.9153 | |
OP | <0.01% | $12.8 | 0.0677 | $0.8669 | |
OP | <0.01% | $140.04 | 0.00612216 | $0.8573 | |
OP | <0.01% | $1 | 0.7539 | $0.7538 | |
OP | <0.01% | $1,758.28 | 0.00033662 | $0.5918 | |
OP | <0.01% | $9.47 | 0.0593 | $0.5619 | |
OP | <0.01% | $0.045246 | 10.5737 | $0.4784 | |
OP | <0.01% | $0.714863 | 0.6559 | $0.4688 | |
OP | <0.01% | $12.8 | 0.0302 | $0.387 | |
OP | <0.01% | $1,605.04 | 0.0002394 | $0.384249 | |
OP | <0.01% | $0.087784 | 4.0163 | $0.3525 | |
OP | <0.01% | $0.670996 | 0.5153 | $0.3457 | |
OP | <0.01% | $0.999966 | 0.3018 | $0.3017 | |
OP | <0.01% | $1,921.82 | 0.00011279 | $0.2167 | |
OP | <0.01% | $1 | 0.1838 | $0.1838 | |
OP | <0.01% | $0.924849 | 0.16 | $0.148 | |
OP | <0.01% | $0.013915 | 9.734 | $0.1354 | |
OP | <0.01% | $5.26 | 0.0246 | $0.1292 | |
OP | <0.01% | $0.192298 | 0.5672 | $0.109 | |
OP | <0.01% | $0.99999 | 0.1041 | $0.104 | |
OP | <0.01% | $2.45 | 0.0411 | $0.1008 |
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.