More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Swapper
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 20000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IEVault, IERC20} from "evk/EVault/IEVault.sol"; import {SafeERC20Lib} from "evk/EVault/shared/lib/SafeERC20Lib.sol"; import {RevertBytes} from "evk/EVault/shared/lib/RevertBytes.sol"; import {ISwapper} from "./ISwapper.sol"; import {GenericHandler} from "./handlers/GenericHandler.sol"; import {UniswapV2Handler} from "./handlers/UniswapV2Handler.sol"; import {UniswapV3Handler} from "./handlers/UniswapV3Handler.sol"; /// @title Swapper /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Untrusted helper contract for EVK for performing swaps and swaps to repay contract Swapper is GenericHandler, UniswapV2Handler, UniswapV3Handler { bytes32 public constant HANDLER_GENERIC = bytes32("Generic"); bytes32 public constant HANDLER_UNISWAP_V2 = bytes32("UniswapV2"); bytes32 public constant HANDLER_UNISWAP_V3 = bytes32("UniswapV3"); uint256 internal constant REENTRANCYLOCK_UNLOCKED = 1; uint256 internal constant REENTRANCYLOCK_LOCKED = 2; uint256 private reentrancyLock; error Swapper_UnknownMode(); error Swapper_UnknownHandler(); error Swapper_Reentrancy(); // In the locked state, allow contract to call itself, but block all external calls modifier externalLock() { bool isExternal = msg.sender != address(this); if (isExternal) { if (reentrancyLock == REENTRANCYLOCK_LOCKED) revert Swapper_Reentrancy(); reentrancyLock = REENTRANCYLOCK_LOCKED; } _; if (isExternal) reentrancyLock = REENTRANCYLOCK_UNLOCKED; } constructor(address uniswapRouterV2, address uniswapRouterV3) UniswapV2Handler(uniswapRouterV2) UniswapV3Handler(uniswapRouterV3) {} /// @inheritdoc ISwapper function swap(SwapParams memory params) public externalLock { if (params.mode >= MODE_MAX_VALUE) revert Swapper_UnknownMode(); if (params.handler == HANDLER_GENERIC) { swapGeneric(params); } else if (params.handler == HANDLER_UNISWAP_V2) { swapUniswapV2(params); } else if (params.handler == HANDLER_UNISWAP_V3) { swapUniswapV3(params); } else { revert Swapper_UnknownHandler(); } if (params.mode == MODE_EXACT_IN) return; // swapping to target debt is only useful for repaying if (params.mode == MODE_TARGET_DEBT) { // at this point amountOut holds the required repay amount _repayAndDeposit(params.tokenOut, params.receiver, params.amountOut, params.account); } // return unused input token after exact output swap _deposit(params.tokenIn, params.vaultIn, 0, params.accountIn); } /// @inheritdoc ISwapper /// @dev in case of over-swapping to repay, pass max uint amount function repay(address token, address vault, uint256 repayAmount, address account) public externalLock { setMaxAllowance(token, vault); uint256 balance = IERC20(token).balanceOf(address(this)); repayAmount = _capRepayToBalance(repayAmount, balance); IEVault(vault).repay(repayAmount, account); } /// @inheritdoc ISwapper function repayAndDeposit(address token, address vault, uint256 repayAmount, address account) public externalLock { _repayAndDeposit(token, vault, repayAmount, account); } /// @inheritdoc ISwapper function deposit(address token, address vault, uint256 amountMin, address account) public externalLock { _deposit(token, vault, amountMin, account); } /// @inheritdoc ISwapper function sweep(address token, uint256 amountMin, address to) public externalLock { uint256 balance = IERC20(token).balanceOf(address(this)); if (balance >= amountMin) { SafeERC20Lib.safeTransfer(IERC20(token), to, balance); } } /// @inheritdoc ISwapper function multicall(bytes[] memory calls) external externalLock { for (uint256 i; i < calls.length; i++) { (bool success, bytes memory result) = address(this).call(calls[i]); if (!success) RevertBytes.revertBytes(result); } } // internal function _deposit(address token, address vault, uint256 amountMin, address account) internal { setMaxAllowance(token, vault); uint256 balance = IERC20(token).balanceOf(address(this)); if (balance >= amountMin) { IEVault(vault).deposit(balance, account); } } function _repayAndDeposit(address token, address vault, uint256 repayAmount, address account) internal { setMaxAllowance(token, vault); uint256 balance = IERC20(token).balanceOf(address(this)); repayAmount = _capRepayToBalance(repayAmount, balance); repayAmount = IEVault(vault).repay(repayAmount, account); if (balance > repayAmount) { IEVault(vault).deposit(type(uint256).max, account); } } // Adjust repay to the available balance. It is needed when exact output swaps are not exact in reality. // It is user's responsibility to verify the debt is within accepted limits after the call to Swapper function _capRepayToBalance(uint256 repayAmount, uint256 balance) internal pure returns (uint256) { if (repayAmount != type(uint256).max && repayAmount > balance) { repayAmount = balance; } return repayAmount; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import {IVault as IEVCVault} from "ethereum-vault-connector/interfaces/IVault.sol"; // Full interface of EVault and all it's modules /// @title IInitialize /// @notice Interface of the initialization module of EVault interface IInitialize { /// @notice Initialization of the newly deployed proxy contract /// @param proxyCreator Account which created the proxy or should be the initial governor function initialize(address proxyCreator) external; } /// @title IERC20 /// @notice Interface of the EVault's Initialize module interface IERC20 { /// @notice Vault share token (eToken) name, ie "Euler Vault: DAI" /// @return The name of the eToken function name() external view returns (string memory); /// @notice Vault share token (eToken) symbol, ie "eDAI" /// @return The symbol of the eToken function symbol() external view returns (string memory); /// @notice Decimals, the same as the asset's or 18 if the asset doesn't implement `decimals()` /// @return The decimals of the eToken function decimals() external view returns (uint8); /// @notice Sum of all eToken balances /// @return The total supply of the eToken function totalSupply() external view returns (uint256); /// @notice Balance of a particular account, in eTokens /// @param account Address to query /// @return The balance of the account function balanceOf(address account) external view returns (uint256); /// @notice Retrieve the current allowance /// @param holder The account holding the eTokens /// @param spender Trusted address /// @return The allowance from holder for spender function allowance(address holder, address spender) external view returns (uint256); /// @notice Transfer eTokens to another address /// @param to Recipient account /// @param amount In shares. /// @return True if transfer succeeded function transfer(address to, uint256 amount) external returns (bool); /// @notice Transfer eTokens from one address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @param amount In shares /// @return True if transfer succeeded function transferFrom(address from, address to, uint256 amount) external returns (bool); /// @notice Allow spender to access an amount of your eTokens /// @param spender Trusted address /// @param amount Use max uint for "infinite" allowance /// @return True if approval succeeded function approve(address spender, uint256 amount) external returns (bool); } /// @title IToken /// @notice Interface of the EVault's Token module interface IToken is IERC20 { /// @notice Transfer the full eToken balance of an address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @return True if transfer succeeded function transferFromMax(address from, address to) external returns (bool); } /// @title IERC4626 /// @notice Interface of an ERC4626 vault interface IERC4626 { /// @notice Vault's underlying asset /// @return The vault's underlying asset function asset() external view returns (address); /// @notice Total amount of managed assets, cash and borrows /// @return The total amount of assets function totalAssets() external view returns (uint256); /// @notice Calculate amount of assets corresponding to the requested shares amount /// @param shares Amount of shares to convert /// @return The amount of assets function convertToAssets(uint256 shares) external view returns (uint256); /// @notice Calculate amount of shares corresponding to the requested assets amount /// @param assets Amount of assets to convert /// @return The amount of shares function convertToShares(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user can deposit /// @param account Address to query /// @return The max amount of assets the account can deposit function maxDeposit(address account) external view returns (uint256); /// @notice Calculate an amount of shares that would be created by depositing assets /// @param assets Amount of assets deposited /// @return Amount of shares received function previewDeposit(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user can mint /// @param account Address to query /// @return The max amount of shares the account can mint function maxMint(address account) external view returns (uint256); /// @notice Calculate an amount of assets that would be required to mint requested amount of shares /// @param shares Amount of shares to be minted /// @return Required amount of assets function previewMint(uint256 shares) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user is allowed to withdraw /// @param owner Account holding the shares /// @return The maximum amount of assets the owner is allowed to withdraw function maxWithdraw(address owner) external view returns (uint256); /// @notice Calculate the amount of shares that will be burned when withdrawing requested amount of assets /// @param assets Amount of assets withdrawn /// @return Amount of shares burned function previewWithdraw(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user is allowed to redeem for assets /// @param owner Account holding the shares /// @return The maximum amount of shares the owner is allowed to redeem function maxRedeem(address owner) external view returns (uint256); /// @notice Calculate the amount of assets that will be transferred when redeeming requested amount of shares /// @param shares Amount of shares redeemed /// @return Amount of assets transferred function previewRedeem(uint256 shares) external view returns (uint256); /// @notice Transfer requested amount of underlying tokens from sender to the vault pool in return for shares /// @param amount Amount of assets to deposit (use max uint256 for full underlying token balance) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Deposit will round down the amount of assets that are converted to shares. To prevent losses consider using /// mint instead. function deposit(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from sender to the vault pool in return for requested amount of shares /// @param amount Amount of shares to be minted /// @param receiver An account to receive the shares /// @return Amount of assets deposited function mint(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer requested amount of underlying tokens from the vault and decrease account's shares balance /// @param amount Amount of assets to withdraw /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn /// @return Amount of shares burned function withdraw(uint256 amount, address receiver, address owner) external returns (uint256); /// @notice Burn requested shares and transfer corresponding underlying tokens from the vault to the receiver /// @param amount Amount of shares to burn (use max uint256 to burn full owner balance) /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn. /// @return Amount of assets transferred function redeem(uint256 amount, address receiver, address owner) external returns (uint256); } /// @title IVault /// @notice Interface of the EVault's Vault module interface IVault is IERC4626 { /// @notice Balance of the fees accumulator, in shares /// @return The accumulated fees in shares function accumulatedFees() external view returns (uint256); /// @notice Balance of the fees accumulator, in underlying units /// @return The accumulated fees in asset units function accumulatedFeesAssets() external view returns (uint256); /// @notice Address of the original vault creator /// @return The address of the creator function creator() external view returns (address); /// @notice Creates shares for the receiver, from excess asset balances of the vault (not accounted for in `cash`) /// @param amount Amount of assets to claim (use max uint256 to claim all available assets) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Could be used as an alternative deposit flow in certain scenarios. E.g. swap directly to the vault, call /// `skim` to claim deposit. function skim(uint256 amount, address receiver) external returns (uint256); } /// @title IBorrowing /// @notice Interface of the EVault's Borrowing module interface IBorrowing { /// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued) /// @return The total borrows in asset units function totalBorrows() external view returns (uint256); /// @notice Sum of all outstanding debts, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @return The total borrows in internal debt precision function totalBorrowsExact() external view returns (uint256); /// @notice Balance of vault assets as tracked by deposits/withdrawals and borrows/repays /// @return The amount of assets the vault tracks as current direct holdings function cash() external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units /// @param account Address to query /// @return The debt of the account in asset units function debtOf(address account) external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @param account Address to query /// @return The debt of the account in internal precision function debtOfExact(address account) external view returns (uint256); /// @notice Retrieves the current interest rate for an asset /// @return The interest rate in yield-per-second, scaled by 10**27 function interestRate() external view returns (uint256); /// @notice Retrieves the current interest rate accumulator for an asset /// @return An opaque accumulator that increases as interest is accrued function interestAccumulator() external view returns (uint256); /// @notice Returns an address of the sidecar DToken /// @return The address of the DToken function dToken() external view returns (address); /// @notice Transfer underlying tokens from the vault to the sender, and increase sender's debt /// @param amount Amount of assets to borrow (use max uint256 for all available tokens) /// @param receiver Account receiving the borrowed tokens /// @return Amount of assets borrowed function borrow(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from the sender to the vault, and decrease receiver's debt /// @param amount Amount of debt to repay in assets (use max uint256 for full debt) /// @param receiver Account holding the debt to be repaid /// @return Amount of assets repaid function repay(uint256 amount, address receiver) external returns (uint256); /// @notice Pay off liability with shares ("self-repay") /// @param amount In asset units (use max uint256 to repay the debt in full or up to the available deposit) /// @param receiver Account to remove debt from by burning sender's shares /// @return shares Amount of shares burned /// @return debt Amount of debt removed in assets /// @dev Equivalent to withdrawing and repaying, but no assets are needed to be present in the vault /// @dev Contrary to a regular `repay`, if account is unhealthy, the repay amount must bring the account back to /// health, or the operation will revert during account status check function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt); /// @notice Take over debt from another account /// @param amount Amount of debt in asset units (use max uint256 for all the account's debt) /// @param from Account to pull the debt from /// @dev Due to internal debt precision accounting, the liability reported on either or both accounts after /// calling `pullDebt` may not match the `amount` requested precisely function pullDebt(uint256 amount, address from) external; /// @notice Request a flash-loan. A onFlashLoan() callback in msg.sender will be invoked, which must repay the loan /// to the main Euler address prior to returning. /// @param amount In asset units /// @param data Passed through to the onFlashLoan() callback, so contracts don't need to store transient data in /// storage function flashLoan(uint256 amount, bytes calldata data) external; /// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs /// vault status function touch() external; } /// @title ILiquidation /// @notice Interface of the EVault's Liquidation module interface ILiquidation { /// @notice Checks to see if a liquidation would be profitable, without actually doing anything /// @param liquidator Address that will initiate the liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @return maxRepay Max amount of debt that can be repaid, in asset units /// @return maxYield Yield in collateral corresponding to max allowed amount of debt to be repaid, in collateral /// balance (shares for vaults) function checkLiquidation(address liquidator, address violator, address collateral) external view returns (uint256 maxRepay, uint256 maxYield); /// @notice Attempts to perform a liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @param repayAssets The amount of underlying debt to be transferred from violator to sender, in asset units (use /// max uint256 to repay the maximum possible amount). Meant as slippage check together with `minYieldBalance` /// @param minYieldBalance The minimum acceptable amount of collateral to be transferred from violator to sender, in /// collateral balance units (shares for vaults). Meant as slippage check together with `repayAssets` /// @dev If `repayAssets` is set to max uint256 it is assumed the caller will perform their own slippage checks to /// make sure they are not taking on too much debt. This option is mainly meant for smart contract liquidators function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external; } /// @title IRiskManager /// @notice Interface of the EVault's RiskManager module interface IRiskManager is IEVCVault { /// @notice Retrieve account's total liquidity /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collateralValue Total risk adjusted value of all collaterals in unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidity(address account, bool liquidation) external view returns (uint256 collateralValue, uint256 liabilityValue); /// @notice Retrieve account's liquidity per collateral /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collaterals Array of collaterals enabled /// @return collateralValues Array of risk adjusted collateral values corresponding to items in collaterals array. /// In unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidityFull(address account, bool liquidation) external view returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue); /// @notice Release control of the account on EVC if no outstanding debt is present function disableController() external; /// @notice Checks the status of an account and reverts if account is not healthy /// @param account The address of the account to be checked /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkAccountStatus(address account, address[] calldata collaterals) external view returns (bytes4); /// @notice Checks the status of the vault and reverts if caps are exceeded /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkVaultStatus() external returns (bytes4); } /// @title IBalanceForwarder /// @notice Interface of the EVault's BalanceForwarder module interface IBalanceForwarder { /// @notice Retrieve the address of rewards contract, tracking changes in account's balances /// @return The balance tracker address function balanceTrackerAddress() external view returns (address); /// @notice Retrieves boolean indicating if the account opted in to forward balance changes to the rewards contract /// @param account Address to query /// @return True if balance forwarder is enabled function balanceForwarderEnabled(address account) external view returns (bool); /// @notice Enables balance forwarding for the authenticated account /// @dev Only the authenticated account can enable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the current account's balance function enableBalanceForwarder() external; /// @notice Disables balance forwarding for the authenticated account /// @dev Only the authenticated account can disable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the account's balance of 0 function disableBalanceForwarder() external; } /// @title IGovernance /// @notice Interface of the EVault's Governance module interface IGovernance { /// @notice Retrieves the address of the governor /// @return The governor address function governorAdmin() external view returns (address); /// @notice Retrieves address of the governance fee receiver /// @return The fee receiver address function feeReceiver() external view returns (address); /// @notice Retrieves the interest fee in effect for the vault /// @return Amount of interest that is redirected as a fee, as a fraction scaled by 1e4 function interestFee() external view returns (uint16); /// @notice Looks up an asset's currently configured interest rate model /// @return Address of the interest rate contract or address zero to indicate 0% interest function interestRateModel() external view returns (address); /// @notice Retrieves the ProtocolConfig address /// @return The protocol config address function protocolConfigAddress() external view returns (address); /// @notice Retrieves the protocol fee share /// @return A percentage share of fees accrued belonging to the protocol, in 1e4 scale function protocolFeeShare() external view returns (uint256); /// @notice Retrieves the address which will receive protocol's fees /// @notice The protocol fee receiver address function protocolFeeReceiver() external view returns (address); /// @notice Retrieves supply and borrow caps in AmountCap format /// @return supplyCap The supply cap in AmountCap format /// @return borrowCap The borrow cap in AmountCap format function caps() external view returns (uint16 supplyCap, uint16 borrowCap); /// @notice Retrieves the borrow LTV of the collateral, which is used to determine if the account is healthy during /// account status checks. /// @param collateral The address of the collateral to query /// @return Borrowing LTV in 1e4 scale function LTVBorrow(address collateral) external view returns (uint16); /// @notice Retrieves the current liquidation LTV, which is used to determine if the account is eligible for /// liquidation /// @param collateral The address of the collateral to query /// @return Liquidation LTV in 1e4 scale function LTVLiquidation(address collateral) external view returns (uint16); /// @notice Retrieves LTV configuration for the collateral /// @param collateral Collateral asset /// @return borrowLTV The current value of borrow LTV for originating positions /// @return liquidationLTV The value of fully converged liquidation LTV /// @return initialLiquidationLTV The initial value of the liquidation LTV, when the ramp began /// @return targetTimestamp The timestamp when the liquidation LTV is considered fully converged /// @return rampDuration The time it takes for the liquidation LTV to converge from the initial value to the fully /// converged value function LTVFull(address collateral) external view returns ( uint16 borrowLTV, uint16 liquidationLTV, uint16 initialLiquidationLTV, uint48 targetTimestamp, uint32 rampDuration ); /// @notice Retrieves a list of collaterals with configured LTVs /// @return List of asset collaterals /// @dev Returned assets could have the ltv disabled (set to zero) function LTVList() external view returns (address[] memory); /// @notice Retrieves the maximum liquidation discount /// @return The maximum liquidation discount in 1e4 scale /// @dev The default value, which is zero, is deliberately bad, as it means there would be no incentive to liquidate /// unhealthy users. The vault creator must take care to properly select the limit, given the underlying and /// collaterals used. function maxLiquidationDiscount() external view returns (uint16); /// @notice Retrieves liquidation cool-off time, which must elapse after successful account status check before /// account can be liquidated /// @return The liquidation cool off time in seconds function liquidationCoolOffTime() external view returns (uint16); /// @notice Retrieves a hook target and a bitmask indicating which operations call the hook target /// @return hookTarget Address of the hook target contract /// @return hookedOps Bitmask with operations that should call the hooks. See Constants.sol for a list of operations function hookConfig() external view returns (address hookTarget, uint32 hookedOps); /// @notice Retrieves a bitmask indicating enabled config flags /// @return Bitmask with config flags enabled function configFlags() external view returns (uint32); /// @notice Address of EthereumVaultConnector contract /// @return The EVC address function EVC() external view returns (address); /// @notice Retrieves a reference asset used for liquidity calculations /// @return The address of the reference asset function unitOfAccount() external view returns (address); /// @notice Retrieves the address of the oracle contract /// @return The address of the oracle function oracle() external view returns (address); /// @notice Retrieves the Permit2 contract address /// @return The address of the Permit2 contract function permit2Address() external view returns (address); /// @notice Splits accrued fees balance according to protocol fee share and transfers shares to the governor fee /// receiver and protocol fee receiver function convertFees() external; /// @notice Set a new governor address /// @param newGovernorAdmin The new governor address /// @dev Set to zero address to renounce privileges and make the vault non-governed function setGovernorAdmin(address newGovernorAdmin) external; /// @notice Set a new governor fee receiver address /// @param newFeeReceiver The new fee receiver address function setFeeReceiver(address newFeeReceiver) external; /// @notice Set a new LTV config /// @param collateral Address of collateral to set LTV for /// @param borrowLTV New borrow LTV, for assessing account's health during account status checks, in 1e4 scale /// @param liquidationLTV New liquidation LTV after ramp ends in 1e4 scale /// @param rampDuration Ramp duration in seconds function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external; /// @notice Set a new maximum liquidation discount /// @param newDiscount New maximum liquidation discount in 1e4 scale /// @dev If the discount is zero (the default), the liquidators will not be incentivized to liquidate unhealthy /// accounts function setMaxLiquidationDiscount(uint16 newDiscount) external; /// @notice Set a new liquidation cool off time, which must elapse after successful account status check before /// account can be liquidated /// @param newCoolOffTime The new liquidation cool off time in seconds /// @dev Setting cool off time to zero allows liquidating the account in the same block as the last successful /// account status check function setLiquidationCoolOffTime(uint16 newCoolOffTime) external; /// @notice Set a new interest rate model contract /// @param newModel The new IRM address /// @dev If the new model reverts, perhaps due to governor error, the vault will silently use a zero interest /// rate. Governor should make sure the new interest rates are computed as expected. function setInterestRateModel(address newModel) external; /// @notice Set a new hook target and a new bitmap indicating which operations should call the hook target. /// Operations are defined in Constants.sol. /// @param newHookTarget The new hook target address. Use address(0) to simply disable hooked operations /// @param newHookedOps Bitmask with the new hooked operations /// @dev All operations are initially disabled in a newly created vault. The vault creator must set their /// own configuration to make the vault usable function setHookConfig(address newHookTarget, uint32 newHookedOps) external; /// @notice Set new bitmap indicating which config flags should be enabled. Flags are defined in Constants.sol /// @param newConfigFlags Bitmask with the new config flags function setConfigFlags(uint32 newConfigFlags) external; /// @notice Set new supply and borrow caps in AmountCap format /// @param supplyCap The new supply cap in AmountCap fromat /// @param borrowCap The new borrow cap in AmountCap fromat function setCaps(uint16 supplyCap, uint16 borrowCap) external; /// @notice Set a new interest fee /// @param newFee The new interest fee function setInterestFee(uint16 newFee) external; } /// @title IEVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Interface of the EVault, an EVC enabled lending vault interface IEVault is IInitialize, IToken, IVault, IBorrowing, ILiquidation, IRiskManager, IBalanceForwarder, IGovernance { /// @notice Fetch address of the `Initialize` module function MODULE_INITIALIZE() external view returns (address); /// @notice Fetch address of the `Token` module function MODULE_TOKEN() external view returns (address); /// @notice Fetch address of the `Vault` module function MODULE_VAULT() external view returns (address); /// @notice Fetch address of the `Borrowing` module function MODULE_BORROWING() external view returns (address); /// @notice Fetch address of the `Liquidation` module function MODULE_LIQUIDATION() external view returns (address); /// @notice Fetch address of the `RiskManager` module function MODULE_RISKMANAGER() external view returns (address); /// @notice Fetch address of the `BalanceForwarder` module function MODULE_BALANCE_FORWARDER() external view returns (address); /// @notice Fetch address of the `Governance` module function MODULE_GOVERNANCE() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IERC20} from "../../IEVault.sol"; import {RevertBytes} from "./RevertBytes.sol"; import {IPermit2} from "../../../interfaces/IPermit2.sol"; /// @title SafeERC20Lib Library /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice The library provides helpers for ERC20 transfers, including Permit2 support library SafeERC20Lib { error E_TransferFromFailed(bytes errorPermit2, bytes errorTransferFrom); // If no code exists under the token address, the function will succeed. EVault ensures this is not the case in // `initialize`. function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool, bytes memory) { (bool success, bytes memory data) = address(token).call(abi.encodeCall(IERC20.transferFrom, (from, to, value))); return isEmptyOrTrueReturn(success, data) ? (true, bytes("")) : (false, data); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value, address permit2) internal { bool success; bytes memory permit2Data; bytes memory transferData; if (permit2 != address(0) && value <= type(uint160).max) { // it's safe to down-cast value to uint160 (success, permit2Data) = permit2.call(abi.encodeCall(IPermit2.transferFrom, (from, to, uint160(value), address(token)))); } if (!success) { (success, transferData) = trySafeTransferFrom(token, from, to, value); } if (!success) revert E_TransferFromFailed(permit2Data, transferData); } // If no code exists under the token address, the function will succeed. EVault ensures this is not the case in // `initialize`. function safeTransfer(IERC20 token, address to, uint256 value) internal { (bool success, bytes memory data) = address(token).call(abi.encodeCall(IERC20.transfer, (to, value))); if (!isEmptyOrTrueReturn(success, data)) RevertBytes.revertBytes(data); } function isEmptyOrTrueReturn(bool callSuccess, bytes memory data) private pure returns (bool) { return callSuccess && (data.length == 0 || (data.length >= 32 && abi.decode(data, (bool)))); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "../Errors.sol"; /// @title RevertBytes Library /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice The library provides a helper function for bubbling up errors library RevertBytes { function revertBytes(bytes memory errMsg) internal pure { if (errMsg.length > 0) { assembly { revert(add(32, errMsg), mload(errMsg)) } } revert Errors.E_EmptyError(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title ISwapper /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Interface of helper contracts, which handle swapping of assets for Euler Vault Kit interface ISwapper { /// @title SwapParams /// @notice This struct holds all the parameters needed to carry out a swap struct SwapParams { // An id of the swap handler to use bytes32 handler; // Swap mode to execute // 0 - exact input swap // 1 - exect output swap // 2 - exact output swap and repay, targeting a debt amount of an account uint256 mode; // An EVC compatible account address, used e.g. as receiver of repay in swap and repay mode address account; // Sold asset address tokenIn; // Bought asset address tokenOut; // Vault to which the unused input in exact output swap will be deposited back address vaultIn; // An EVC compatible account address, to which the unused input in exact output swap will be deposited back address accountIn; // In swapping modes (0 and 1) - address of the intended recipient of the bought tokens // In swap and repay mode (2) - address of the liability vault of the account, where to repay debt // Note that if the swap uses off-chain encoded payload, the receiver might be ignored. The user // should verify the assets are in fact in the receiver address after the swap address receiver; // In exact input mode (0) - ignored // In exact output mode (1) - amount of `tokenOut` to buy // In swap and repay mode (2) - amount of debt the account should have after swap and repay. // To repay all debt without leaving any dust, set this to zero. uint256 amountOut; // Auxiliary payload for swap providers. For GenericHandler it's an abi encoded tuple: target contract address // and call data bytes data; } /// @notice Execute a swap (and possibly repay or deposit) according to the SwapParams configuration /// @param params Configuration of the swap function swap(SwapParams calldata params) external; /// @notice Use the contract's token balance to repay debt of the account in a lending vault /// @param token The asset that is borrowed /// @param vault The lending vault where the debt is tracked /// @param repayAmount Amount of debt to repay /// @param account Receiver of the repay /// @dev If contract's balance is lower than requested repay amount, repay only the balance function repay(address token, address vault, uint256 repayAmount, address account) external; /// @notice Use the contract's token balance to repay debt of the account in a lending vault /// and deposit any remaining balance for the account in that same vault /// @param token The asset that is borrowed /// @param vault The lending vault where the debt is tracked /// @param repayAmount Amount of debt to repay /// @param account Receiver of the repay /// @dev If contract's balance is lower than requested repay amount, repay only the balance function repayAndDeposit(address token, address vault, uint256 repayAmount, address account) external; /// @notice Use all of the contract's token balance to execute a deposit for an account /// @param token Asset to deposit /// @param vault Vault to deposit the token to /// @param amountMin A minimum amount of tokens to deposit. If unavailable, the operation is a no-op /// @param account Receiver of the repay /// @dev Use amountMin to ignore dust function deposit(address token, address vault, uint256 amountMin, address account) external; /// @notice Transfer all tokens held by the contract /// @param token Token to transfer /// @param amountMin Minimum amount of tokens to transfer. If unavailable, the operation is a no-op /// @param to Address to send the tokens to function sweep(address token, uint256 amountMin, address to) external; /// @notice Call multiple functions of the contract /// @param calls Array of encoded payloads /// @dev Calls itself with regular external calls function multicall(bytes[] memory calls) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {BaseHandler} from "./BaseHandler.sol"; /// @title GenericHandler /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Swap handler executing arbitrary trades on arbitrary target abstract contract GenericHandler is BaseHandler { /// @dev the handler expects SwapParams.data to contain an abi encoded tuple: target contract address and call data function swapGeneric(SwapParams memory params) internal virtual { (address target, bytes memory payload) = abi.decode(params.data, (address, bytes)); if (params.mode == MODE_TARGET_DEBT) resolveParams(params); // set repay amount in params.amountOut setMaxAllowance(params.tokenIn, target); (bool success, bytes memory result) = target.call(payload); if (!success) revert Swapper_SwapError(target, result); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {BaseHandler} from "./BaseHandler.sol"; import {IUniswapV2Router01} from "../vendor/ISwapRouterV2.sol"; /// @title UniswapV2Handler /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Swap handler executing exact output trades on Uniswap V2 abstract contract UniswapV2Handler is BaseHandler { address public immutable uniswapRouterV2; error UniswapV2Handler_InvalidPath(); constructor(address _uniswapRouterV2) { uniswapRouterV2 = _uniswapRouterV2; } function swapUniswapV2(SwapParams memory params) internal virtual { if (params.mode == MODE_EXACT_IN) revert Swapper_UnsupportedMode(); if (params.data.length < 64 || params.data.length % 32 != 0) revert UniswapV2Handler_InvalidPath(); setMaxAllowance(params.tokenIn, uniswapRouterV2); // process params according to the mode and current state (uint256 amountOut, address receiver) = resolveParams(params); if (amountOut > 0) { (bool success, bytes memory result) = uniswapRouterV2.call( abi.encodeCall( IUniswapV2Router01.swapTokensForExactTokens, (amountOut, type(uint256).max, abi.decode(params.data, (address[])), receiver, block.timestamp) ) ); if (!success) revert Swapper_SwapError(uniswapRouterV2, result); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {BaseHandler} from "./BaseHandler.sol"; import {ISwapRouterV3} from "../vendor/ISwapRouterV3.sol"; /// @title UniswapV3Handler /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Swap handler executing exact output trades on Uniswap V3 abstract contract UniswapV3Handler is BaseHandler { address public immutable uniswapRouterV3; error UniswapV3Handler_InvalidPath(); constructor(address _uniswapRouterV3) { uniswapRouterV3 = _uniswapRouterV3; } function swapUniswapV3(SwapParams memory params) internal virtual { if (params.mode == MODE_EXACT_IN) revert Swapper_UnsupportedMode(); unchecked { if (params.data.length < 43 || (params.data.length - 20) % 23 != 0) revert UniswapV3Handler_InvalidPath(); } setMaxAllowance(params.tokenIn, uniswapRouterV3); // update amountOut and receiver according to the mode and current state (uint256 amountOut, address receiver) = resolveParams(params); if (amountOut > 0) { (bool success, bytes memory result) = uniswapRouterV3.call( abi.encodeCall( ISwapRouterV3.exactOutput, ISwapRouterV3.ExactOutputParams({ path: params.data, recipient: receiver, amountOut: amountOut, amountInMaximum: type(uint256).max, deadline: block.timestamp }) ) ); if (!success) revert Swapper_SwapError(uniswapRouterV3, result); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice This interface defines the methods for the Vault for the purpose of integration with the Ethereum Vault /// Connector. interface IVault { /// @notice Disables a controller (this vault) for the authenticated account. /// @dev A controller is a vault that has been chosen for an account to have special control over account’s /// balances in the enabled collaterals vaults. User calls this function in order for the vault to disable itself /// for the account if the conditions are met (i.e. user has repaid debt in full). If the conditions are not met, /// the function reverts. function disableController() external; /// @notice Checks the status of an account. /// @dev This function must only deliberately revert if the account status is invalid. If this function reverts due /// to any other reason, it may render the account unusable with possibly no way to recover funds. /// @param account The address of the account to be checked. /// @param collaterals The array of enabled collateral addresses to be considered for the account status check. /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkAccountStatus( address account, address[] calldata collaterals ) external view returns (bytes4 magicValue); /// @notice Checks the status of the vault. /// @dev This function must only deliberately revert if the vault status is invalid. If this function reverts due to /// any other reason, it may render some accounts unusable with possibly no way to recover funds. /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkVaultStatus() external returns (bytes4 magicValue); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IPermit2 /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice A minimal interface of the Uniswap's Permit2 contract interface IPermit2 { /// @notice Transfer tokens between two accounts /// @param from The account to send the tokens from /// @param to The account to send the tokens to /// @param amount Amount of tokens to send /// @param token Address of the token contract function transferFrom(address from, address to, uint160 amount, address token) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; /// @title Errors /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Contract implementing EVault's custom errors contract Errors { error E_Initialized(); error E_ProxyMetadata(); error E_SelfTransfer(); error E_InsufficientAllowance(); error E_InsufficientCash(); error E_InsufficientAssets(); error E_InsufficientBalance(); error E_InsufficientDebt(); error E_FlashLoanNotRepaid(); error E_Reentrancy(); error E_OperationDisabled(); error E_OutstandingDebt(); error E_AmountTooLargeToEncode(); error E_DebtAmountTooLargeToEncode(); error E_RepayTooMuch(); error E_TransientState(); error E_SelfLiquidation(); error E_ControllerDisabled(); error E_CollateralDisabled(); error E_ViolatorLiquidityDeferred(); error E_LiquidationCoolOff(); error E_ExcessiveRepayAmount(); error E_MinYield(); error E_BadAddress(); error E_ZeroAssets(); error E_ZeroShares(); error E_Unauthorized(); error E_CheckUnauthorized(); error E_NotSupported(); error E_EmptyError(); error E_BadBorrowCap(); error E_BadSupplyCap(); error E_BadCollateral(); error E_AccountLiquidity(); error E_NoLiability(); error E_NotController(); error E_BadFee(); error E_SupplyCapExceeded(); error E_BorrowCapExceeded(); error E_InvalidLTVAsset(); error E_NoPriceOracle(); error E_ConfigAmountTooLargeToEncode(); error E_BadAssetReceiver(); error E_BadSharesOwner(); error E_BadSharesReceiver(); error E_BadMaxLiquidationDiscount(); error E_LTVBorrow(); error E_LTVLiquidation(); error E_NotHookTarget(); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {ISwapper} from "../ISwapper.sol"; import {IEVault, IERC20} from "evk/EVault/IEVault.sol"; import {RevertBytes} from "evk/EVault/shared/lib/RevertBytes.sol"; /// @title BaseHandler /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Base contract for swap handlers - contracts interfacing with swap providers abstract contract BaseHandler is ISwapper { // exact input swaps - unknown amount of tokens bought for exact amount of tokens sold uint256 internal constant MODE_EXACT_IN = 0; // exact output swaps - exact amount of tokens bought for unknown amount of tokens sold uint256 internal constant MODE_EXACT_OUT = 1; // target debt swap and repay - the amount requested is the debt amount the account should have after swap and repay uint256 internal constant MODE_TARGET_DEBT = 2; // swap modes delimiter uint256 internal constant MODE_MAX_VALUE = 3; error Swapper_UnsupportedMode(); error Swapper_TargetDebt(); error Swapper_SwapError(address swapProvider, bytes rawError); function resolveParams(SwapParams memory params) internal view returns (uint256 amountOut, address receiver) { amountOut = params.amountOut; receiver = params.receiver; if (params.mode == MODE_EXACT_IN) return (amountOut, receiver); uint256 balanceOut = IERC20(params.tokenOut).balanceOf(address(this)); // for combined exact output swaps, which accumulate the output in the swapper, check how much is already // available if (params.mode == MODE_EXACT_OUT && params.receiver == address(this)) { unchecked { amountOut = balanceOut >= amountOut ? 0 : amountOut - balanceOut; } return (amountOut, receiver); } if (params.mode == MODE_TARGET_DEBT) { uint256 debt = IEVault(params.receiver).debtOf(params.account); // amountOut is the target debt if (amountOut > debt) revert Swapper_TargetDebt(); unchecked { // reuse params.amountOut to hold repay amountOut = params.amountOut = debt - amountOut; // check if balance is already sufficient to repay amountOut = balanceOut >= amountOut ? 0 : amountOut - balanceOut; } // collect output in the swapper for repay receiver = address(this); } } function setMaxAllowance(address token, address spender) internal { safeApproveWithRetry(token, spender, type(uint256).max); } function trySafeApprove(address token, address to, uint256 value) internal returns (bool, bytes memory) { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); return (success && (data.length == 0 || abi.decode(data, (bool))), data); } function safeApproveWithRetry(address token, address to, uint256 value) internal { (bool success, bytes memory data) = trySafeApprove(token, to, value); // some tokens, like USDT, require the allowance to be set to 0 first if (!success) { (success,) = trySafeApprove(token, to, 0); if (success) { (success,) = trySafeApprove(token, to, value); } } if (!success) RevertBytes.revertBytes(data); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens(uint256 amountOut, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB); function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountOut); function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); } interface ISwapRouterV2 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import "./IUniswapV3SwapCallback.sol"; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouterV3 is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external; }
{ "remappings": [ "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "ethereum-vault-connector/=lib/ethereum-vault-connector/src/", "evc/=lib/ethereum-vault-connector/src/", "evk/=lib/euler-vault-kit/src/", "evk-test/=lib/euler-vault-kit/test/", "euler-price-oracle/=lib/euler-price-oracle/src/", "euler-price-oracle-test/=lib/euler-price-oracle/test/", "fee-flow/=lib/fee-flow/src/", "reward-streams/=lib/reward-streams/src/", "lib/euler-price-oracle:@openzeppelin/contracts/=lib/euler-price-oracle/lib/openzeppelin-contracts/contracts/", "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "euler-earn/=lib/euler-earn/src/", "@openzeppelin-upgradeable/=lib/euler-earn/lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@pendle/core-v2/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/", "@pyth/=lib/euler-price-oracle/lib/pyth-sdk-solidity/", "@redstone/evm-connector/=lib/euler-price-oracle/lib/redstone-oracles-monorepo/packages/evm-connector/contracts/", "@solady/=lib/euler-price-oracle/lib/solady/src/", "@uniswap/v3-core/=lib/euler-price-oracle/lib/v3-core/", "@uniswap/v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/", "ERC4626/=lib/euler-earn/lib/properties/lib/ERC4626/contracts/", "crytic-properties/=lib/euler-earn/lib/properties/contracts/", "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "euler-vault-kit/=lib/euler-vault-kit/src/", "forge-gas-snapshot/=lib/euler-vault-kit/lib/permit2/lib/forge-gas-snapshot/src/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin/=lib/ethereum-vault-connector/lib/openzeppelin-contracts/contracts/", "pendle-core-v2-public/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/", "permit2/=lib/euler-vault-kit/lib/permit2/", "properties/=lib/euler-earn/lib/properties/contracts/", "pyth-sdk-solidity/=lib/euler-price-oracle/lib/pyth-sdk-solidity/", "redstone-oracles-monorepo/=lib/euler-price-oracle/lib/", "solady/=lib/euler-price-oracle/lib/solady/src/", "solmate/=lib/fee-flow/lib/solmate/src/", "v3-core/=lib/euler-price-oracle/lib/v3-core/contracts/", "v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/contracts/" ], "optimizer": { "enabled": true, "runs": 20000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"uniswapRouterV2","type":"address"},{"internalType":"address","name":"uniswapRouterV3","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"E_EmptyError","type":"error"},{"inputs":[],"name":"Swapper_Reentrancy","type":"error"},{"inputs":[{"internalType":"address","name":"swapProvider","type":"address"},{"internalType":"bytes","name":"rawError","type":"bytes"}],"name":"Swapper_SwapError","type":"error"},{"inputs":[],"name":"Swapper_TargetDebt","type":"error"},{"inputs":[],"name":"Swapper_UnknownHandler","type":"error"},{"inputs":[],"name":"Swapper_UnknownMode","type":"error"},{"inputs":[],"name":"Swapper_UnsupportedMode","type":"error"},{"inputs":[],"name":"UniswapV2Handler_InvalidPath","type":"error"},{"inputs":[],"name":"UniswapV3Handler_InvalidPath","type":"error"},{"inputs":[],"name":"HANDLER_GENERIC","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HANDLER_UNISWAP_V2","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HANDLER_UNISWAP_V3","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"}],"name":"multicall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"repayAndDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"handler","type":"bytes32"},{"internalType":"uint256","name":"mode","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"address","name":"vaultIn","type":"address"},{"internalType":"address","name":"accountIn","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ISwapper.SwapParams","name":"params","type":"tuple"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouterV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapRouterV3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801562000010575f80fd5b5060405162001f2138038062001f21833981016040819052620000339162000067565b6001600160a01b039182166080521660a0526200009d565b80516001600160a01b038116811462000062575f80fd5b919050565b5f806040838503121562000079575f80fd5b62000084836200004b565b915062000094602084016200004b565b90509250929050565b60805160a051611e39620000e85f395f818160cd015281816111190152818161115701526112c901525f818161014601528181610e8801528181610ec601526110170152611e395ff3fe608060405234801561000f575f80fd5b50600436106100c4575f3560e01c8063a55f08d31161007d578063d60116cb11610058578063d60116cb146101fe578063dc2c256f14610211578063f71679d014610224575f80fd5b8063a55f08d31461019d578063ac9650d8146101c4578063c4d88adf146101d7575f80fd5b806352da17a4116100ad57806352da17a41461012e578063596fa9e3146101415780637db6657d14610168575f80fd5b806310f91b0b146100c85780633bc1f1ed14610119575b5f80fd5b6100ef7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61012c6101273660046116e7565b610237565b005b61012c61013c3660046116e7565b61029f565b6100ef7f000000000000000000000000000000000000000000000000000000000000000081565b61018f7f47656e657269630000000000000000000000000000000000000000000000000081565b604051908152602001610110565b61018f7f556e69737761705632000000000000000000000000000000000000000000000081565b61012c6101d2366004611897565b61043a565b61018f7f556e69737761705633000000000000000000000000000000000000000000000081565b61012c61020c3660046116e7565b61053a565b61012c61021f366004611941565b610590565b61012c610232366004611980565b61068e565b3330148015906102815760025f540361027c576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b61028d85858585610839565b80156102985760015f555b5050505050565b3330148015906102e95760025f54036102e4576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6102f38585610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561035d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103819190611a72565b905061038d84826109a4565b6040517facb708150000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff85811660248301529195509086169063acb70815906044016020604051808303815f875af1158015610403573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104279190611a72565b505080156102985760015f555050505050565b3330148015906104845760025f540361047f576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b5f5b825181101561052a575f803073ffffffffffffffffffffffffffffffffffffffff168584815181106104ba576104ba611a89565b60200260200101516040516104cf9190611ad8565b5f604051808303815f865af19150503d805f8114610508576040519150601f19603f3d011682016040523d82523d5f602084013e61050d565b606091505b50915091508161052057610520816109e4565b5050600101610486565b5080156105365760015f555b5050565b3330148015906105845760025f540361057f576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b61028d85858585610a25565b3330148015906105da5760025f54036105d5576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610644573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106689190611a72565b905083811061067c5761067c858483610be7565b5080156106885760015f555b50505050565b3330148015906106d85760025f54036106d3576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6003826020015110610716576040517f70b55f7e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81517fb89a919a8d969d000000000000000000000000000000000000000000000000000161074c5761074782610cf3565b6107e0565b81517faa91968c889e8fa9ce00000000000000000000000000000000000000000000000161077d5761074782610de6565b81517faa91968c889e8fa9cd0000000000000000000000000000000000000000000000016107ae5761074782611070565b6040517f48e355b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201511561082b5760028260200151036108135761081382608001518360e001518461010001518560400151610a25565b61082b82606001518360a001515f8560c00151610839565b80156105365760015f555050565b6108438484610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156108ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108d19190611a72565b9050828110610298576040517f6e553f650000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8381166024830152851690636e553f65906044015b6020604051808303815f875af115801561094d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109719190611a72565b505050505050565b61053682827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61131d565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83141580156109d457508183115b156109dd578192505b5090919050565b8051156109f357805181602001fd5b6040517f2082e20000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a2f8484610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610a99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610abd9190611a72565b9050610ac983826109a4565b6040517facb708150000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff84811660248301529194509085169063acb70815906044016020604051808303815f875af1158015610b3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b639190611a72565b925082811115610298576040517f6e553f650000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152851690636e553f6590604401610931565b60405173ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390525f918291861690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905251610c999190611ad8565b5f604051808303815f865af19150503d805f8114610cd2576040519150601f19603f3d011682016040523d82523d5f602084013e610cd7565b606091505b5091509150610ce68282611364565b61029857610298816109e4565b5f80826101200151806020019051810190610d0e9190611af3565b915091506002836020015103610d2a57610d278361139e565b50505b610d38836060015183610979565b5f808373ffffffffffffffffffffffffffffffffffffffff1683604051610d5f9190611ad8565b5f604051808303815f865af19150503d805f8114610d98576040519150601f19603f3d011682016040523d82523d5f602084013e610d9d565b606091505b5091509150816102985783816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b60405180910390fd5b6020810151610e21576040517fda62918000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040816101200151511080610e475750602081610120015151610e449190611c27565b15155b15610e7e576040517f807d9b7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610eac81606001517f0000000000000000000000000000000000000000000000000000000000000000610979565b5f80610eb78361139e565b9092509050811561106b575f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff876101200151806020019051810190610f369190611c5f565b8642604051602401610f4c959493929190611cf4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8803dbee0000000000000000000000000000000000000000000000000000000017905251610fcd9190611ad8565b5f604051808303815f865af19150503d805f8114611006576040519150601f19603f3d011682016040523d82523d5f602084013e61100b565b606091505b509150915081610298577f0000000000000000000000000000000000000000000000000000000000000000816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b505050565b60208101516110ab576040517fda62918000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602b8161012001515110806110d85750601760148261012001515103816110d4576110d4611bfa565b0615155b1561110f576040517f8f22cca200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61113d81606001517f0000000000000000000000000000000000000000000000000000000000000000610979565b5f806111488361139e565b9092509050811561106b575f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166040518060a0016040528087610120015181526020018573ffffffffffffffffffffffffffffffffffffffff1681526020014281526020018681526020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8152506040516024016111fe9190611d7f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff28c0498000000000000000000000000000000000000000000000000000000001790525161127f9190611ad8565b5f604051808303815f865af19150503d805f81146112b8576040519150601f19603f3d011682016040523d82523d5f602084013e6112bd565b606091505b509150915081610298577f0000000000000000000000000000000000000000000000000000000000000000816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b5f8061132a8585856115a6565b91509150816113565761133e85855f6115a6565b5091508115611356576113528585856115a6565b5091505b8161029857610298816109e4565b5f828015611397575081511580611397575060208251101580156113975750818060200190518101906113979190611de4565b9392505050565b61010081015160e082015160208301516113b757915091565b60808301516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611425573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114499190611a72565b905060018460200151148015611478575060e084015173ffffffffffffffffffffffffffffffffffffffff1630145b15611497578281101561148d5780830361148f565b5f5b925050915091565b60028460200151036115a05760e084015160408086015190517fd283e75f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201525f92919091169063d283e75f90602401602060405180830381865afa15801561151b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061153f9190611a72565b90508084111561157b576040517fb245150100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9283036101008501819052928382101561159757818403611599565b5f5b9350309250505b50915091565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905291515f926060928492839289169161163f91611ad8565b5f604051808303815f865af19150503d805f8114611678576040519150601f19603f3d011682016040523d82523d5f602084013e61167d565b606091505b50915091508180156116a75750805115806116a75750808060200190518101906116a79190611de4565b97909650945050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146116d4575f80fd5b50565b80356116e2816116b3565b919050565b5f805f80608085870312156116fa575f80fd5b8435611705816116b3565b93506020850135611715816116b3565b925060408501359150606085013561172c816116b3565b939692955090935050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610140810167ffffffffffffffff8111828210171561178857611788611737565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156117d5576117d5611737565b604052919050565b5f67ffffffffffffffff8211156117f6576117f6611737565b5060051b60200190565b5f67ffffffffffffffff82111561181957611819611737565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112611854575f80fd5b813561186761186282611800565b61178e565b81815284602083860101111561187b575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208083850312156118a8575f80fd5b823567ffffffffffffffff808211156118bf575f80fd5b818501915085601f8301126118d2575f80fd5b81356118e0611862826117dd565b81815260059190911b830184019084810190888311156118fe575f80fd5b8585015b8381101561193457803585811115611918575f80fd5b6119268b89838a0101611845565b845250918601918601611902565b5098975050505050505050565b5f805f60608486031215611953575f80fd5b833561195e816116b3565b9250602084013591506040840135611975816116b3565b809150509250925092565b5f60208284031215611990575f80fd5b813567ffffffffffffffff808211156119a7575f80fd5b9083019061014082860312156119bb575f80fd5b6119c3611764565b82358152602083013560208201526119dd604084016116d7565b60408201526119ee606084016116d7565b60608201526119ff608084016116d7565b6080820152611a1060a084016116d7565b60a0820152611a2160c084016116d7565b60c0820152611a3260e084016116d7565b60e082015261010083810135908201526101208084013583811115611a55575f80fd5b611a6188828701611845565b918301919091525095945050505050565b5f60208284031215611a82575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5b83811015611ad0578181015183820152602001611ab8565b50505f910152565b5f8251611ae9818460208701611ab6565b9190910192915050565b5f8060408385031215611b04575f80fd5b8251611b0f816116b3565b602084015190925067ffffffffffffffff811115611b2b575f80fd5b8301601f81018513611b3b575f80fd5b8051611b4961186282611800565b818152866020838501011115611b5d575f80fd5b611b6e826020830160208601611ab6565b8093505050509250929050565b5f8151808452611b92816020860160208601611ab6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f611bf26040830184611b7b565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82611c5a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b5f6020808385031215611c70575f80fd5b825167ffffffffffffffff811115611c86575f80fd5b8301601f81018513611c96575f80fd5b8051611ca4611862826117dd565b81815260059190911b82018301908381019087831115611cc2575f80fd5b928401925b82841015611ce9578351611cda816116b3565b82529284019290840190611cc7565b979650505050505050565b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b81811015611d5157845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611d1f565b505073ffffffffffffffffffffffffffffffffffffffff969096166060850152505050608001529392505050565b602081525f825160a06020840152611d9a60c0840182611b7b565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b5f60208284031215611df4575f80fd5b81518015158114611397575f80fdfea2646970667358221220bcce0601ed6b95ba997ab63f34e3bcc4c6dd1b17173329aa82002539ba84522864736f6c634300081800330000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100c4575f3560e01c8063a55f08d31161007d578063d60116cb11610058578063d60116cb146101fe578063dc2c256f14610211578063f71679d014610224575f80fd5b8063a55f08d31461019d578063ac9650d8146101c4578063c4d88adf146101d7575f80fd5b806352da17a4116100ad57806352da17a41461012e578063596fa9e3146101415780637db6657d14610168575f80fd5b806310f91b0b146100c85780633bc1f1ed14610119575b5f80fd5b6100ef7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61012c6101273660046116e7565b610237565b005b61012c61013c3660046116e7565b61029f565b6100ef7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b61018f7f47656e657269630000000000000000000000000000000000000000000000000081565b604051908152602001610110565b61018f7f556e69737761705632000000000000000000000000000000000000000000000081565b61012c6101d2366004611897565b61043a565b61018f7f556e69737761705633000000000000000000000000000000000000000000000081565b61012c61020c3660046116e7565b61053a565b61012c61021f366004611941565b610590565b61012c610232366004611980565b61068e565b3330148015906102815760025f540361027c576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b61028d85858585610839565b80156102985760015f555b5050505050565b3330148015906102e95760025f54036102e4576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6102f38585610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561035d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103819190611a72565b905061038d84826109a4565b6040517facb708150000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff85811660248301529195509086169063acb70815906044016020604051808303815f875af1158015610403573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104279190611a72565b505080156102985760015f555050505050565b3330148015906104845760025f540361047f576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b5f5b825181101561052a575f803073ffffffffffffffffffffffffffffffffffffffff168584815181106104ba576104ba611a89565b60200260200101516040516104cf9190611ad8565b5f604051808303815f865af19150503d805f8114610508576040519150601f19603f3d011682016040523d82523d5f602084013e61050d565b606091505b50915091508161052057610520816109e4565b5050600101610486565b5080156105365760015f555b5050565b3330148015906105845760025f540361057f576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b61028d85858585610a25565b3330148015906105da5760025f54036105d5576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610644573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106689190611a72565b905083811061067c5761067c858483610be7565b5080156106885760015f555b50505050565b3330148015906106d85760025f54036106d3576040517fce17255100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f555b6003826020015110610716576040517f70b55f7e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81517fb89a919a8d969d000000000000000000000000000000000000000000000000000161074c5761074782610cf3565b6107e0565b81517faa91968c889e8fa9ce00000000000000000000000000000000000000000000000161077d5761074782610de6565b81517faa91968c889e8fa9cd0000000000000000000000000000000000000000000000016107ae5761074782611070565b6040517f48e355b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201511561082b5760028260200151036108135761081382608001518360e001518461010001518560400151610a25565b61082b82606001518360a001515f8560c00151610839565b80156105365760015f555050565b6108438484610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156108ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108d19190611a72565b9050828110610298576040517f6e553f650000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8381166024830152851690636e553f65906044015b6020604051808303815f875af115801561094d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109719190611a72565b505050505050565b61053682827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61131d565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83141580156109d457508183115b156109dd578192505b5090919050565b8051156109f357805181602001fd5b6040517f2082e20000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a2f8484610979565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610a99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610abd9190611a72565b9050610ac983826109a4565b6040517facb708150000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff84811660248301529194509085169063acb70815906044016020604051808303815f875af1158015610b3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b639190611a72565b925082811115610298576040517f6e553f650000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152851690636e553f6590604401610931565b60405173ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390525f918291861690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905251610c999190611ad8565b5f604051808303815f865af19150503d805f8114610cd2576040519150601f19603f3d011682016040523d82523d5f602084013e610cd7565b606091505b5091509150610ce68282611364565b61029857610298816109e4565b5f80826101200151806020019051810190610d0e9190611af3565b915091506002836020015103610d2a57610d278361139e565b50505b610d38836060015183610979565b5f808373ffffffffffffffffffffffffffffffffffffffff1683604051610d5f9190611ad8565b5f604051808303815f865af19150503d805f8114610d98576040519150601f19603f3d011682016040523d82523d5f602084013e610d9d565b606091505b5091509150816102985783816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b60405180910390fd5b6020810151610e21576040517fda62918000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040816101200151511080610e475750602081610120015151610e449190611c27565b15155b15610e7e576040517f807d9b7b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610eac81606001517f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d610979565b5f80610eb78361139e565b9092509050811561106b575f807f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff16847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff876101200151806020019051810190610f369190611c5f565b8642604051602401610f4c959493929190611cf4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8803dbee0000000000000000000000000000000000000000000000000000000017905251610fcd9190611ad8565b5f604051808303815f865af19150503d805f8114611006576040519150601f19603f3d011682016040523d82523d5f602084013e61100b565b606091505b509150915081610298577f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b505050565b60208101516110ab576040517fda62918000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602b8161012001515110806110d85750601760148261012001515103816110d4576110d4611bfa565b0615155b1561110f576040517f8f22cca200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61113d81606001517f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564610979565b5f806111488361139e565b9092509050811561106b575f807f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156473ffffffffffffffffffffffffffffffffffffffff166040518060a0016040528087610120015181526020018573ffffffffffffffffffffffffffffffffffffffff1681526020014281526020018681526020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8152506040516024016111fe9190611d7f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff28c0498000000000000000000000000000000000000000000000000000000001790525161127f9190611ad8565b5f604051808303815f865af19150503d805f81146112b8576040519150601f19603f3d011682016040523d82523d5f602084013e6112bd565b606091505b509150915081610298577f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564816040517f436fa211000000000000000000000000000000000000000000000000000000008152600401610ddd929190611bc4565b5f8061132a8585856115a6565b91509150816113565761133e85855f6115a6565b5091508115611356576113528585856115a6565b5091505b8161029857610298816109e4565b5f828015611397575081511580611397575060208251101580156113975750818060200190518101906113979190611de4565b9392505050565b61010081015160e082015160208301516113b757915091565b60808301516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611425573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114499190611a72565b905060018460200151148015611478575060e084015173ffffffffffffffffffffffffffffffffffffffff1630145b15611497578281101561148d5780830361148f565b5f5b925050915091565b60028460200151036115a05760e084015160408086015190517fd283e75f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201525f92919091169063d283e75f90602401602060405180830381865afa15801561151b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061153f9190611a72565b90508084111561157b576040517fb245150100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9283036101008501819052928382101561159757818403611599565b5f5b9350309250505b50915091565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905291515f926060928492839289169161163f91611ad8565b5f604051808303815f865af19150503d805f8114611678576040519150601f19603f3d011682016040523d82523d5f602084013e61167d565b606091505b50915091508180156116a75750805115806116a75750808060200190518101906116a79190611de4565b97909650945050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146116d4575f80fd5b50565b80356116e2816116b3565b919050565b5f805f80608085870312156116fa575f80fd5b8435611705816116b3565b93506020850135611715816116b3565b925060408501359150606085013561172c816116b3565b939692955090935050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610140810167ffffffffffffffff8111828210171561178857611788611737565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156117d5576117d5611737565b604052919050565b5f67ffffffffffffffff8211156117f6576117f6611737565b5060051b60200190565b5f67ffffffffffffffff82111561181957611819611737565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112611854575f80fd5b813561186761186282611800565b61178e565b81815284602083860101111561187b575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208083850312156118a8575f80fd5b823567ffffffffffffffff808211156118bf575f80fd5b818501915085601f8301126118d2575f80fd5b81356118e0611862826117dd565b81815260059190911b830184019084810190888311156118fe575f80fd5b8585015b8381101561193457803585811115611918575f80fd5b6119268b89838a0101611845565b845250918601918601611902565b5098975050505050505050565b5f805f60608486031215611953575f80fd5b833561195e816116b3565b9250602084013591506040840135611975816116b3565b809150509250925092565b5f60208284031215611990575f80fd5b813567ffffffffffffffff808211156119a7575f80fd5b9083019061014082860312156119bb575f80fd5b6119c3611764565b82358152602083013560208201526119dd604084016116d7565b60408201526119ee606084016116d7565b60608201526119ff608084016116d7565b6080820152611a1060a084016116d7565b60a0820152611a2160c084016116d7565b60c0820152611a3260e084016116d7565b60e082015261010083810135908201526101208084013583811115611a55575f80fd5b611a6188828701611845565b918301919091525095945050505050565b5f60208284031215611a82575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5b83811015611ad0578181015183820152602001611ab8565b50505f910152565b5f8251611ae9818460208701611ab6565b9190910192915050565b5f8060408385031215611b04575f80fd5b8251611b0f816116b3565b602084015190925067ffffffffffffffff811115611b2b575f80fd5b8301601f81018513611b3b575f80fd5b8051611b4961186282611800565b818152866020838501011115611b5d575f80fd5b611b6e826020830160208601611ab6565b8093505050509250929050565b5f8151808452611b92816020860160208601611ab6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f611bf26040830184611b7b565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82611c5a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b5f6020808385031215611c70575f80fd5b825167ffffffffffffffff811115611c86575f80fd5b8301601f81018513611c96575f80fd5b8051611ca4611862826117dd565b81815260059190911b82018301908381019087831115611cc2575f80fd5b928401925b82841015611ce9578351611cda816116b3565b82529284019290840190611cc7565b979650505050505050565b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b81811015611d5157845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611d1f565b505073ffffffffffffffffffffffffffffffffffffffff969096166060850152505050608001529392505050565b602081525f825160a06020840152611d9a60c0840182611b7b565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b5f60208284031215611df4575f80fd5b81518015158114611397575f80fdfea2646970667358221220bcce0601ed6b95ba997ab63f34e3bcc4c6dd1b17173329aa82002539ba84522864736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
-----Decoded View---------------
Arg [0] : uniswapRouterV2 (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [1] : uniswapRouterV3 (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [1] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.