ETH Price: $2,018.87 (+3.90%)

Contract

0x1785ecf144C20e0d4f7321F60bCbCD8f167A61b3
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Deposit With Tok...245045802026-02-21 10:16:1116 days ago1771668971IN
0x1785ecf1...f167A61b3
0 ETH0.000029990.03325621
Deposit With Tok...244972742026-02-20 9:49:4717 days ago1771580987IN
0x1785ecf1...f167A61b3
0 ETH0.000047990.05340037
Deposit With Tok...244967232026-02-20 7:58:5917 days ago1771574339IN
0x1785ecf1...f167A61b3
0 ETH0.000036180.04134785
Deposit With Tok...244910122026-02-19 12:52:1118 days ago1771505531IN
0x1785ecf1...f167A61b3
0 ETH0.000081850.09233593
Deposit With Tok...244824792026-02-18 8:18:5919 days ago1771402739IN
0x1785ecf1...f167A61b3
0 ETH0.000034980.03858325
Deposit With Tok...244391582026-02-12 7:19:1125 days ago1770880751IN
0x1785ecf1...f167A61b3
0 ETH0.000065630.07152437
Deposit With Tok...244192522026-02-09 12:37:2328 days ago1770640643IN
0x1785ecf1...f167A61b3
0 ETH0.000003270.06346993
Deposit With Tok...244192512026-02-09 12:37:1128 days ago1770640631IN
0x1785ecf1...f167A61b3
0 ETH0.000054340.06046559
Deposit With Tok...244190542026-02-09 11:57:4728 days ago1770638267IN
0x1785ecf1...f167A61b3
0 ETH0.000058810.06498803
Deposit With Tok...244182952026-02-09 9:24:2328 days ago1770629063IN
0x1785ecf1...f167A61b3
0 ETH0.000068930.07562726
Deposit With Tok...244050512026-02-07 12:49:4730 days ago1770468587IN
0x1785ecf1...f167A61b3
0 ETH0.000109530.12186534
Deposit With Tok...244047112026-02-07 11:41:3530 days ago1770464495IN
0x1785ecf1...f167A61b3
0 ETH0.000099340.10995493
Deposit With Tok...243971232026-02-06 10:15:4731 days ago1770372947IN
0x1785ecf1...f167A61b3
0 ETH0.000313880.3474203
Deposit With Tok...243970682026-02-06 10:04:4731 days ago1770372287IN
0x1785ecf1...f167A61b3
0 ETH0.000342810.38815152
Deposit With Tok...243969592026-02-06 9:42:3531 days ago1770370955IN
0x1785ecf1...f167A61b3
0 ETH0.000358420.40951286
Deposit With Tok...243968672026-02-06 9:24:1131 days ago1770369851IN
0x1785ecf1...f167A61b3
0 ETH0.000266490.3022362
Deposit With Tok...243961162026-02-06 6:53:1131 days ago1770360791IN
0x1785ecf1...f167A61b3
0 ETH0.000446350.50725366
Deposit With Tok...243900152026-02-05 10:24:3532 days ago1770287075IN
0x1785ecf1...f167A61b3
0 ETH0.000161430.18278968
Deposit With Tok...243894702026-02-05 8:34:5932 days ago1770280499IN
0x1785ecf1...f167A61b3
0 ETH0.000224730.24784939
Deposit With Tok...243893862026-02-05 8:17:4732 days ago1770279467IN
0x1785ecf1...f167A61b3
0 ETH0.000128070.14524844
Deposit With Tok...243892332026-02-05 7:46:5932 days ago1770277619IN
0x1785ecf1...f167A61b3
0 ETH0.000211970.23499403
Deposit With Tok...243835712026-02-04 12:44:4733 days ago1770209087IN
0x1785ecf1...f167A61b3
0 ETH0.000187710.21176619
Deposit With Tok...243835432026-02-04 12:39:1133 days ago1770208751IN
0x1785ecf1...f167A61b3
0 ETH0.000240540.27236122
Deposit With Tok...243832422026-02-04 11:38:3533 days ago1770205115IN
0x1785ecf1...f167A61b3
0 ETH0.000303830.34275255
Deposit With Tok...243824082026-02-04 8:51:4733 days ago1770195107IN
0x1785ecf1...f167A61b3
0 ETH0.000126420.14599567
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VaultRouter

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 10000 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IERC4626} from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";
import {IUniversalDexModule} from "../interfaces/IUniversalDexModule.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Errors} from "../common/Errors.sol";
import {DataTypes} from "../common/DataTypes.sol";
import {IDepositManager} from "../interfaces/IDepositManager.sol";

/**
 * @title VaultRouter
 * @author Superlend
 * @notice Router contract for vault deposits with optional token swapping
 * @dev Handles deposits into vaults with automatic token conversion when needed
 */
contract VaultRouter is Ownable {
    /**
     * @notice Emitted when a vault is whitelisted or unwhitelisted
     * @param vault The address of the vault
     * @param isWhitelisted True if the vault is whitelisted, false if it is unwhitelisted
     */
    event VaultWhitelisted(address indexed vault, bool isWhitelisted);

    /**
     * @notice Emitted when a token is whitelisted or unwhitelisted
     * @param token The address of the token
     * @param isWhitelisted True if the token is whitelisted, false if it is unwhitelisted
     */
    event TokenWhitelisted(address indexed token, bool isWhitelisted);

    /**
     * @notice Emitted when a deposit manager is whitelisted or unwhitelisted
     * @param depositManager The address of the deposit manager
     * @param isWhitelisted True if the deposit manager is whitelisted, false if it is unwhitelisted
     */
    event DepositManagerWhitelisted(address indexed depositManager, bool isWhitelisted);

    /**
     * @notice Mapping of supported vault addresses to their whitelist status
     */
    mapping(address => bool) public supportedVaults;

    /**
     * @notice Mapping of supported token addresses to their whitelist status
     */
    mapping(address => bool) public supportedTokens;

    /**
     * @notice Mapping of supported deposit manager addresses to their whitelist status
     */
    mapping(address => bool) public supportedDepositManagers;

    /**
     * @notice The universal DEX module for token swaps
     */
    IUniversalDexModule public universalDexModule;

    /**
     * @notice Constructor to initialize the vault router
     * @param _supportedVaults Array of initially supported vault addresses
     * @param _supportedTokens Array of initially supported token addresses
     * @param _universalDexModule The address of the universal DEX module
     * @param _supportedDepositManagers Array of initially supported deposit manager addresses
     */
    constructor(
        address[] memory _supportedVaults,
        address[] memory _supportedTokens,
        address _universalDexModule,
        address[] memory _supportedDepositManagers
    ) Ownable(_msgSender()) {
        for (uint256 i = 0; i < _supportedVaults.length; i++) {
            supportedVaults[_supportedVaults[i]] = true;

            emit VaultWhitelisted(_supportedVaults[i], true);
        }

        for (uint256 i = 0; i < _supportedTokens.length; i++) {
            supportedTokens[_supportedTokens[i]] = true;

            emit TokenWhitelisted(_supportedTokens[i], true);
        }

        for (uint256 i = 0; i < _supportedDepositManagers.length; i++) {
            supportedDepositManagers[_supportedDepositManagers[i]] = true;

            emit DepositManagerWhitelisted(_supportedDepositManagers[i], true);
        }

        universalDexModule = IUniversalDexModule(_universalDexModule);
    }

    /**
     * @notice Deposits tokens into a vault with optional swap functionality
     * @param vault The address of the target vault
     * @param tokenIn The address of the input token
     * @param amountIn The amount of input tokens to deposit
     * @param swapParams Parameters for executing a swap if needed
     */
    function depositWithToken(
        address vault,
        address depositManager,
        address tokenIn,
        uint256 amountIn,
        DataTypes.DepositType depositType,
        DataTypes.ExecuteSwapParams memory swapParams
    ) external {
        require(supportedVaults[vault], Errors.VAULT_NOT_WHITELISTED);
        require(supportedTokens[tokenIn], Errors.TOKEN_NOT_WHITELISTED);
        require(supportedDepositManagers[depositManager], Errors.DEPOSIT_MANAGER_NOT_WHITELISTED);

        address vaultAsset = IERC4626(vault).asset();
        uint256 tokenInBalanceBefore = IERC20(tokenIn).balanceOf(address(this));
        SafeERC20.safeTransferFrom(IERC20(tokenIn), _msgSender(), address(this), amountIn);

        if (vaultAsset == tokenIn) {
            _handleDeposit(vault, depositManager, tokenIn, amountIn, depositType);
            return;
        }

        SafeERC20.forceApprove(IERC20(tokenIn), address(universalDexModule), amountIn);
        uint256 amountOut = universalDexModule.executeAndExit(swapParams, address(this));
        uint256 tokenInBalanceAfter = IERC20(tokenIn).balanceOf(address(this));

        uint256 tokenInAmountLeft = tokenInBalanceAfter - tokenInBalanceBefore;
        if (tokenInAmountLeft > 0) {
            SafeERC20.safeTransfer(IERC20(tokenIn), _msgSender(), tokenInAmountLeft);
        }

        _handleDeposit(vault, depositManager, vaultAsset, amountOut, depositType);
    }

    /**
     * @notice Adds or removes a vault from the whitelist (restricted to owner)
     * @param vault The address of the vault to whitelist/unwhitelist
     * @param isWhitelisted True to whitelist, false to remove from whitelist
     */
    function whitelistVault(address vault, bool isWhitelisted) external onlyOwner {
        supportedVaults[vault] = isWhitelisted;

        emit VaultWhitelisted(vault, isWhitelisted);
    }

    /**
     * @notice Adds or removes a token from the whitelist (restricted to owner)
     * @param token The address of the token to whitelist/unwhitelist
     * @param isWhitelisted True to whitelist, false to remove from whitelist
     */
    function whitelistToken(address token, bool isWhitelisted) external onlyOwner {
        supportedTokens[token] = isWhitelisted;

        emit TokenWhitelisted(token, isWhitelisted);
    }

    /**
     * @notice Adds or removes a deposit manager from the whitelist (restricted to owner)
     * @param depositManager The address of the deposit manager to whitelist/unwhitelist
     * @param isWhitelisted True to whitelist, false to remove from whitelist
     */
    function whitelistDepositManager(address depositManager, bool isWhitelisted) external onlyOwner {
        supportedDepositManagers[depositManager] = isWhitelisted;

        emit DepositManagerWhitelisted(depositManager, isWhitelisted);
    }

    /**
     * @notice Sets the universal DEX module address (restricted to owner)
     * @param _universalDexModule The address of the universal DEX module
     */
    function setUniversalDexModule(address _universalDexModule) external onlyOwner {
        universalDexModule = IUniversalDexModule(_universalDexModule);
    }

    /**
     * @notice Handles the deposit based on the deposit type
     * @param vault The address of the vault
     * @param depositManager The address of the deposit manager
     * @param tokenIn The address of the input token
     * @param amountIn The amount of input tokens to deposit
     * @param depositType The type of deposit
     */
    function _handleDeposit(
        address vault,
        address depositManager,
        address tokenIn,
        uint256 amountIn,
        DataTypes.DepositType depositType
    ) internal {
        if (depositType == DataTypes.DepositType.INSTANT) {
            _instantDeposit(vault, tokenIn, amountIn);
        } else {
            _requestedDeposit(depositManager, tokenIn, amountIn);
        }
    }

    /**
     * @notice Handles the instant deposit
     * @param vault The address of the vault
     * @param tokenIn The address of the input token
     * @param amountIn The amount of input tokens to deposit
     */
    function _instantDeposit(address vault, address tokenIn, uint256 amountIn) internal {
        SafeERC20.forceApprove(IERC20(tokenIn), vault, amountIn);
        IERC4626(vault).deposit(amountIn, _msgSender());
    }

    /**
     * @notice Handles the requested deposit
     * @param depositManager The address of the deposit manager
     * @param tokenIn The address of the input token
     * @param amountIn The amount of input tokens to deposit
     */
    function _requestedDeposit(address depositManager, address tokenIn, uint256 amountIn) internal {
        SafeERC20.forceApprove(IERC20(tokenIn), depositManager, amountIn);
        IDepositManager(depositManager).requestDeposit(amountIn, _msgSender());
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import {DataTypes} from "../common/DataTypes.sol";

/**
 * @title IUniversalDexModule
 * @author Superlend
 * @notice Interface for universal DEX module operations
 * @dev Handles token swaps and exchange operations across multiple DEX protocols
 */
interface IUniversalDexModule {
    /**
     * @notice Executes a token swap operation
     * @param params The parameters for the swap operation
     * @return The amount of output tokens received
     */
    function execute(DataTypes.ExecuteSwapParams memory params) external returns (uint256);

    /**
     * @notice Executes a token swap and transfers the result to a specified address
     * @param params The parameters for the swap operation
     * @param to The address to receive the swapped tokens
     * @return The amount of output tokens received
     */
    function executeAndExit(DataTypes.ExecuteSwapParams memory params, address to) external returns (uint256);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 7 of 15 : Errors.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @title Errors
 * @author Superlend
 * @notice Library containing all error constants used throughout the Superloop protocol
 * @dev Centralized error definitions for consistent error handling across contracts
 */
library Errors {
    string public constant INVALID_ADDRESS = "1"; // address must not be 0
    string public constant INVALID_MODULE_NAME = "2"; // module name empty
    string public constant INVALID_AMOUNT = "3"; // amount cannot be 0
    string public constant WITHDRAW_REQUEST_ACTIVE = "5"; // one acitve withdraw request already exist
    string public constant INVALID_WITHDRAW_RESOLVED_START_ID_LIMIT = "6"; // new start id should be = old end id + 1
    string public constant INVALID_WITHDRAW_RESOLVED_END_ID_LIMIT = "7"; // new end id should be < current id
    string public constant CALLER_NOT_VAULT = "8"; // the caller of function is not vault
    string public constant INVALID_WITHDRAW_REQUEST_STATE = "9"; // incorrect withdraw request state
    string public constant INVALID_ASSETS_DISTRIBUTED = "10"; // total assets distributed does not match total assets redeemed
    string public constant WITHDRAW_REQUEST_NOT_FOUND = "11"; // withdraw request not found
    string public constant WITHDRAW_REQUEST_ALREADY_CLAIMED = "12"; // withdraw request already claimed
    string public constant WITHDRAW_REQUEST_NOT_RESOLVED = "13"; // withdraw request not resolved
    string public constant CALLER_NOT_WITHDRAW_REQUEST_OWNER = "14"; // the caller of function is not the owner of the withdraw request
    string public constant INVALID_PERFORMANCE_FEE = "15"; // performance fee is greater than max performance fee
    string public constant INVALID_MODULE = "16"; // module is not whitelisted
    string public constant INVALID_SWAP_DATA = "17"; // invalid swap data
    string public constant INVALID_AMOUNT_IN = "18"; // amount in is greater than max amount in
    string public constant INVALID_AMOUNT_OUT = "19"; // amount out is less than min amount out
    string public constant SUPPLY_CAP_EXCEEDED = "21"; // supply cap exceeded
    string public constant INVALID_SHARES_AMOUNT = "22"; // shares amount cannot be 0
    string public constant INSUFFICIENT_BALANCE = "23"; // insufficient balance
    string public constant CALLER_NOT_PRIVILEGED = "24"; // the caller of function is not privileged
    string public constant NOT_IN_EXECUTION_CONTEXT = "25"; // the caller of function is not in execution context
    string public constant MODULE_NOT_REGISTERED = "26"; // module is not registered
    string public constant CALLBACK_HANDLER_NOT_FOUND = "27"; // callback handler not found
    string public constant CALLER_NOT_SELF = "28"; // the caller of function is not self
    string public constant CALLER_NOT_VAULT_ADMIN = "29"; // the caller of function is not vault admin
    string public constant INVALID_SKIM_ASSET = "30"; // invalid asset
    string public constant VAULT_NOT_WHITELISTED = "31"; // vault is not whitelisted
    string public constant TOKEN_NOT_WHITELISTED = "32"; // token is not whitelisted
    string public constant INSTANT_WITHDRAW_NOT_ENABLED = "33"; // instant withdraw is not enabled
    string public constant WITHDRAW_REQUEST_UNCLAIMED = "34"; // withdraw request is unclaimed
    string public constant INVALID_CASH_RESERVE = "35"; // invalid cash reserve
    string public constant INSUFFICIENT_CASH_SHORTFALL = "36"; // insufficient cash shortfall
    string public constant DEPOSIT_REQUEST_ACTIVE = "37"; // deposit request is active
    string public constant DEPOSIT_REQUEST_ALREADY_CANCELLED = "38"; // deposit request already cancelled
    string public constant CALLER_NOT_DEPOSIT_REQUEST_OWNER = "39"; // the caller of function is not the owner of the deposit request
    string public constant DEPOSIT_REQUEST_ALREADY_PROCESSED = "40"; // deposit request already processed
    string public constant INVALID_ASSET = "41"; // invalid asset
    string public constant CALLER_NOT_DEPOSIT_MANAGER = "42"; // the caller of function is not deposit manager
    string public constant DEPOSIT_REQUEST_NOT_FOUND = "43"; // deposit request not found
    string public constant CANNOT_CLAIM_ZERO_AMOUNT = "44"; // cannot claim zero amount
    string public constant CALLER_NOT_WITHDRAW_MANAGER = "45"; // the caller of function is not withdraw manager
    string public constant CALLER_NOT_VAULT_OPERATOR_OR_VAULT_ADMIN = "46"; // the caller of function is not vault operator
    string public constant VAULT_PAUSED = "47"; // vault is paused
    string public constant VAULT_FROZEN = "48"; // vault is frozen
    string public constant DEPOSIT_MANAGER_NOT_WHITELISTED = "49"; // deposit manager is not whitelisted
    string public constant FALLBACK_HANDLER_NOT_FOUND = "50"; // fallback handler not found
    string public constant INVALID_FALLBACK_DATA = "51"; // invalid fallback data

    // Preliquidation
    string public constant PRELIQUIDATION_PRELTV_TOO_HIGH = "52"; // preltv is too high
    string public constant PRELIQUIDATION_LCF_DECREASING = "53"; // lcf is decreasing
    string public constant PRELIQUIDATION_LCF_TOO_HIGH = "54"; // lcf is too high
    string public constant PRELIQUIDATION_LIF_TOO_LOW = "55"; // lif is too low
    string public constant PRELIQUIDATION_LIF_DECREASING = "56"; // lif is decreasing
    string public constant PRELIQUIDATION_LIF_TOO_HIGH = "57"; // lif is too high
    string public constant PRELIQUIDATION_INVALID_ID = "58"; // id is invalid
    string public constant PRELIQUIDATION_INVALID_USER = "59"; // user is invalid
    string public constant PRELIQUIDATION_POSSIBLE_BAD_DEBT = "60"; // possible bad debt
    string public constant PRELIQUIDATION_NOT_IN_PRELIQUIDATION_STATE = "61"; // not in preliquidation state

    // Aave V3 Preliquidation
    string public constant AAVE_V3_PRELIQUIDATION_INVALID_EMODE_CATEGORY = "62"; // reserve is not in the correct emode category
    string public constant AAVE_V3_PRELIQUIDATION_INVALID_LLTV = "63"; // lltv is invalid

    // Superloop
    string public constant VAULT_ALREADY_SEEDED = "64"; // vault already seeded
    string public constant INVALID_INSTANT_WITHDRAW_FEE = "65"; // instant withdraw fee is greater than max instant withdraw fee
}

File 8 of 15 : DataTypes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @title DataTypes
 * @author Superlend
 * @notice Library containing all data structures and enums used throughout the Superloop protocol
 * @dev Centralized data type definitions for consistent usage across contracts
 */
library DataTypes {
    /**
     * @notice Structure for storing module information
     * @param moduleName The name identifier of the module
     * @param moduleAddress The contract address of the module
     */
    struct ModuleData {
        string moduleName;
        address moduleAddress;
    }

    struct ExchangeRateSnapshot {
        uint256 totalSupplyBefore;
        uint256 totalSupplyAfter;
        uint256 totalAssetsBefore;
        uint256 totalAssetsAfter;
    }

    enum RequestProcessingState {
        NOT_EXIST,
        UNPROCESSED,
        PARTIALLY_PROCESSED, // partially processed means that the deposit request has been partially processed
        PARTIALLY_CANCELLED, // partially cancelled means that the deposit request has been partially cancelled
        FULLY_PROCESSED,
        CANCELLED
    }

    struct DepositRequestData {
        uint256 amount;
        uint256 amountProcessed; // amoutn remaining => amount - amountProcessed
        uint256 sharesMinted;
        address user;
        RequestProcessingState state;
    }

    struct ResolveDepositRequestsData {
        address asset;
        uint256 amount;
        bytes callbackExecutionData;
    }

    enum WithdrawRequestType {
        GENERAL, // general queue
        DEFERRED, // low slippage queue
        PRIORITY, // medium slippage queue
        INSTANT // high slippage queue

    }

    struct WithdrawQueue {
        uint256 nextWithdrawRequestId;
        uint256 resolutionIdPointer;
        mapping(uint256 => DataTypes.WithdrawRequestData) withdrawRequest;
        mapping(address => uint256) userWithdrawRequestId;
        uint256 totalPendingWithdraws;
    }

    struct WithdrawRequestData {
        uint256 shares;
        uint256 sharesProcessed;
        uint256 amountClaimable;
        uint256 amountClaimed;
        address user;
        RequestProcessingState state;
    }

    struct ResolveWithdrawRequestsData {
        uint256 shares;
        WithdrawRequestType requestType;
        bytes callbackExecutionData;
    }

    /**
     * @notice Structure for storing withdrawal request information
     * @param shares The number of shares requested for withdrawal
     * @param amount The amount of underlying asset for withdrawal
     * @param user The address of the user making the withdrawal request
     * @param claimed Whether the withdrawal has been claimed
     * @param cancelled Whether the withdrawal request has been cancelled
     */
    struct WithdrawRequestDataLegacy {
        uint256 shares;
        uint256 amount;
        address user;
        bool claimed;
        bool cancelled;
    }

    /**
     * @notice Enumeration of possible withdrawal request states
     */
    enum WithdrawRequestStateLegacy {
        NOT_EXIST, // Request does not exist
        CLAIMED, // Request has been claimed
        UNPROCESSED, // Request is pending processing
        CLAIMABLE, // Request is ready to be claimed
        CANCELLED // Request has been cancelled

    }

    /**
     * @notice Structure for vault initialization data
     * @param asset The address of the underlying asset
     * @param name The name of the vault
     * @param symbol The symbol of the vault
     * @param supplyCap The maximum supply cap for the vault
     * @param minimumDepositAmount The minimum deposit amount for the vault
     * @param instantWithdrawFee The instant withdraw fee for the vault
     * @param superloopModuleRegistry The address of the module registry
     * @param modules Array of module addresses to register
     * @param cashReserve The amount of cash reserve for the vault. Represented in BPS
     * @param accountant The address of the accountant module
     * @param withdrawManager The address of the withdraw manager module
     * @param vaultAdmin The address of the vault admin
     * @param treasury The address of the treasury
     * @param vaultOperator The address of the vault operator
     */
    struct VaultInitData {
        // vault specific
        address asset;
        string name;
        string symbol;
        // superloop specific
        uint256 supplyCap;
        uint256 minimumDepositAmount;
        uint256 instantWithdrawFee;
        address superloopModuleRegistry;
        address[] modules;
        uint256 cashReserve;
        // essential roles
        address accountant;
        address withdrawManager;
        address depositManager;
        address vaultAdmin;
        address treasury;
        address vaultOperator;
    }

    /**
     * @notice Structure for universal DEX module swap execution data
     * @param target The target contract address for the swap
     * @param data The encoded function call data
     */
    struct ExecuteSwapParamsData {
        address target;
        bytes data;
    }

    /**
     * @notice Structure for complete swap execution parameters
     * @param tokenIn The address of the input token
     * @param tokenOut The address of the output token
     * @param amountIn The amount of input tokens
     * @param maxAmountIn The maximum amount of input tokens allowed
     * @param minAmountOut The minimum amount of output tokens expected
     * @param data Array of swap execution data for multi-step swaps
     */
    struct ExecuteSwapParams {
        address tokenIn;
        address tokenOut;
        uint256 amountIn;
        uint256 maxAmountIn;
        uint256 minAmountOut;
        ExecuteSwapParamsData[] data;
    }

    /**
     * @notice Structure for tracking balance differences before and after operations
     * @param tokenInBalanceBefore Balance of input token before operation
     * @param tokenOutBalanceBefore Balance of output token before operation
     * @param tokenInBalanceAfter Balance of input token after operation
     * @param tokenOutBalanceAfter Balance of output token after operation
     */
    struct BalancesDifference {
        uint256 tokenInBalanceBefore;
        uint256 tokenOutBalanceBefore;
        uint256 tokenInBalanceAfter;
        uint256 tokenOutBalanceAfter;
    }

    /**
     * @notice Structure for Aave V3 accountant module initialization
     * @param poolAddressesProvider The Aave pool addresses provider
     * @param lendAssets Array of assets available for lending
     * @param borrowAssets Array of assets available for borrowing
     * @param performanceFee The performance fee percentage
     * @param vault The address of the associated vault
     */
    struct AaveV3AccountantModuleInitData {
        address poolAddressesProvider;
        address[] lendAssets;
        address[] borrowAssets;
        uint16 performanceFee;
        address vault;
    }

    /**
     * @notice Structure for module execution data
     * @param executionType The type of call to execute (CALL or DELEGATECALL)
     * @param module The address of the module to execute
     * @param data The encoded function call data
     */
    struct ModuleExecutionData {
        CallType executionType;
        address module;
        bytes data;
    }

    /**
     * @notice Enumeration of call types for module execution
     */
    enum CallType {
        CALL, // Regular call to external contract
        DELEGATECALL // Delegate call to external contract

    }

    /**
     * @notice Structure for Aave V3 flashloan parameters
     * @param asset The address of the asset to flashloan
     * @param amount The amount to flashloan
     * @param referralCode The referral code for Aave
     * @param callbackExecutionData The data to execute in the flashloan callback
     */
    struct AaveV3FlashloanParams {
        address asset;
        uint256 amount;
        uint16 referralCode;
        bytes callbackExecutionData;
    }

    /**
     * @notice Structure for callback execution data
     * @param asset The address of the asset involved
     * @param addressToApprove The address to approve tokens for
     * @param amountToApprove The amount to approve
     * @param executionData The data to execute in the callback
     */
    struct CallbackData {
        address asset;
        address addressToApprove;
        uint256 amountToApprove;
        bytes executionData;
    }

    /**
     * @notice Structure for Aave V3 eMode parameters
     * @param emodeCategory The eMode category to set
     */
    struct AaveV3EmodeParams {
        uint8 emodeCategory;
    }

    /**
     * @notice Structure for Aave V3 action parameters
     * @param asset The address of the asset
     * @param amount The amount of the asset
     */
    struct AaveV3ActionParams {
        address asset;
        uint256 amount;
    }

    /**
     * @notice Structure for Aave V3 accountant module initialization
     * @param registeredAccountants Array of registered accountant addresses
     * @param performanceFee The performance fee percentage
     * @param vault The address of the associated vault
     */
    struct UniversalAccountantModuleInitData {
        address[] registeredAccountants;
        uint16 performanceFee;
        address vault;
    }

    /**
     * @notice Structure for Aave V3 accountant plugin module initialization
     * @param poolAddressesProvider The Aave pool addresses provider
     * @param lendAssets Array of assets available for lending
     * @param borrowAssets Array of assets available for borrowing
     */
    struct AaveV3AccountantPluginModuleInitData {
        address poolAddressesProvider;
        address[] lendAssets;
        address[] borrowAssets;
    }

    /**
     * @notice Structure for stake parameters
     * @param assets The amount of assets to stake
     * @param data Any additional data to pass to the stake module
     */
    struct StakeParams {
        uint256 assets;
        bytes data;
    }

    enum DepositType {
        INSTANT,
        REQUESTED
    }

    /**
     * @notice Structure for Aave V3 preliquidation parameters
     * @param user The address of the user
     * @param debtToCover The amount of debt to cover
     */
    struct AaveV3ExecutePreliquidationParams {
        address user;
        uint256 debtToCover;
    }

    /**
     * @notice Structure for Aave V3 preliquidation initialization parameters
     * @param id The id of the preliquidation contract, used to make sure fallback handler is configured correctly
     * @param lendReserve The address of the lend reserve
     * @param borrowReserve The address of the borrow reserve
     * @param preLltv The preliquidation ltv
     * @param preCF1 The preliquidation c1
     * @param preCF2 The preliquidation c2
     * @param preIF1 The preliquidation i1
     * @param preIF2 The preliquidation i2
     */
    struct AaveV3PreliquidationParamsInit {
        bytes32 id;
        address lendReserve;
        address borrowReserve;
        uint256 preLltv;
        uint256 preCF1;
        uint256 preCF2;
        uint256 preIF1;
        uint256 preIF2;
    }

    /**
     * @notice Structure for Aave V3 preliquidation parameters
     * @param lendReserve The address of the lend reserve
     * @param borrowReserve The address of the borrow reserve
     * @param Lltv The ltv
     * @param preLltv The preliquidation ltv
     * @param preCF1 The preliquidation c1
     * @param preCF2 The preliquidation c2
     * @param preIF1 The preliquidation i1
     * @param preIF2 The preliquidation i2
     */
    struct AaveV3PreliquidationParams {
        address lendReserve;
        address borrowReserve;
        uint256 Lltv;
        uint256 preLltv;
        uint256 preCF1;
        uint256 preCF2;
        uint256 preIF1;
        uint256 preIF2;
    }

    /**
     * @notice Structure for Merkl claim parameters
     * @param users The addresses of the users to claim rewards for
     * @param tokens The addresses of the tokens to claim rewards for
     * @param amounts The amounts of the tokens to claim rewards for
     * @param proofs The proofs of the Merkle tree
     */
    struct MerklClaimParams {
        address[] users;
        address[] tokens;
        uint256[] amounts;
        bytes32[][] proofs;
    }

    /**
     * @notice Structure for vault action parameters
     * @param vault The address of the vault
     * @param amount The amount of the vault to supply
     */
    struct VaultActionParams {
        address vault;
        uint256 amount;
    }

    /**
     * @notice Structure for Morpho flashloan parameters
     * @param asset The address of the asset to flashloan
     * @param amount The amount to flashloan
     * @param callbackExecutionData The data to execute in the flashloan callback
     */
    struct MorphoFlashloanParams {
        address asset;
        uint256 amount;
        bytes callbackExecutionData;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/**
 * @title IDepositManager
 * @author Superlend
 * @notice Interface for deposit manager operations
 * @dev Handles deposit request creation and management
 */
interface IDepositManager {
    /**
     * @notice Creates a deposit request for the specified amount
     * @param amount The amount of assets to deposit
     * @param onBehalfOf The address to deposit on behalf of
     */
    function requestDeposit(uint256 amount, address onBehalfOf) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 13 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 14 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "aave-v3-core/=lib/aave-v3-core/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "morpho-blue/=lib/morpho-blue/src/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "ds-test/=lib/morpho-blue/lib/forge-std/lib/ds-test/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address[]","name":"_supportedVaults","type":"address[]"},{"internalType":"address[]","name":"_supportedTokens","type":"address[]"},{"internalType":"address","name":"_universalDexModule","type":"address"},{"internalType":"address[]","name":"_supportedDepositManagers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositManager","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"DepositManagerWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"TokenWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"VaultWhitelisted","type":"event"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"depositManager","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"enum DataTypes.DepositType","name":"depositType","type":"uint8"},{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DataTypes.ExecuteSwapParamsData[]","name":"data","type":"tuple[]"}],"internalType":"struct DataTypes.ExecuteSwapParams","name":"swapParams","type":"tuple"}],"name":"depositWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_universalDexModule","type":"address"}],"name":"setUniversalDexModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedDepositManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedVaults","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"universalDexModule","outputs":[{"internalType":"contract IUniversalDexModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositManager","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"whitelistDepositManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"whitelistToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"whitelistVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052346102875761161d803803806100198161028b565b9283398101906080818303126102875780516001600160401b03811161028757826100459183016102d8565b60208201516001600160401b03811161028757836100649184016102d8565b91610071604082016102c4565b60608201519094906001600160401b0381116102875761009192016102d8565b3315610274575f8054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a35f5b8251811015610153576001906001600160a01b036100fb8286610342565b51165f528160205260405f208260ff19825416179055818060a01b036101218286610342565b51167f9652e0d255e1984241157f0e5f65c662604b493e181fde308bc5b66d116d63fe6020604051858152a2016100dd565b8482855f5b81518110156101cf576001906001600160a01b036101768285610342565b51165f52600260205260405f208260ff19825416179055818060a01b0361019d8285610342565b51167fef81a9943b96c8df4ef243401c9bf5159146166211356898b52d382086168d926020604051858152a201610158565b50505f5b815181101561024a576001906001600160a01b036101f18285610342565b51165f52600360205260405f208260ff19825416179055818060a01b036102188285610342565b51167fa97560bd93588927d79d92af36657c64b68481447620f4696e4fe9bf7ce2439a6020604051858152a2016101d3565b600480546001600160a01b0319166001600160a01b0385161790556040516112b2908161036b8239f35b631e4fbdf760e01b5f525f60045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176102b057604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361028757565b9080601f83011215610287578151916001600160401b0383116102b0578260051b9060208061030881850161028b565b80968152019282010192831161028757602001905b82821061032a5750505090565b60208091610337846102c4565b81520191019061031d565b80518210156103565760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c80630ffb1d8b1461076157806338fcfe7a146107175780634133f100146106b357806368c4ac2614610669578063715018a6146105ed578063750b1537146105ba5780638da5cb5b14610588578063b5c3d68d146104f7578063b71b73c3146104ad578063e0f8a1d21461020b578063e6e66c681461016f5763f2fde38b1461009d575f80fd5b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6100cb6107f2565b6100d3610f04565b16801561013f5773ffffffffffffffffffffffffffffffffffffffff5f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f80fd5b3461016b5773ffffffffffffffffffffffffffffffffffffffff7f9652e0d255e1984241157f0e5f65c662604b493e181fde308bc5b66d116d63fe60206101b536610836565b93906101bf610f04565b1692835f52600182526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a2005b3461016b5760c060031936011261016b576102246107f2565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361016b576044359073ffffffffffffffffffffffffffffffffffffffff8216820361016b5760843590600282101561016b5760a4359267ffffffffffffffff841161016b5760c0600319853603011261016b576040519360c0850185811067ffffffffffffffff821117610480576040526102be81600401610815565b85526102cc60248201610815565b602086015260448101356040860152606481013560608601526084810135608086015260a48101359067ffffffffffffffff821161016b5701943660238701121561016b57600486013567ffffffffffffffff8111610480578060051b966040519161033b60208a0184610872565b8252602082019781016024019036821161016b5760248101985b828a1061037457505050610372965060a08601526064359261094f565b005b893567ffffffffffffffff811161016b576004908301019060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0833603011261016b57604051916040830183811067ffffffffffffffff821117610480576040526103e260208201610815565b8352604081013567ffffffffffffffff811161016b5760209101019036601f8301121561016b5781359267ffffffffffffffff841161048057604051610450601f86017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200182610872565b848152366020868601011161016b575f602086819782809801838601378301015283820152815201990198610355565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6104db6107f2565b165f526001602052602060ff60405f2054166040519015158152f35b3461016b5773ffffffffffffffffffffffffffffffffffffffff7fa97560bd93588927d79d92af36657c64b68481447620f4696e4fe9bf7ce2439a602061053d36610836565b9390610547610f04565b1692835f52600382526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b3461016b575f60031936011261016b57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461016b575f60031936011261016b57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b3461016b575f60031936011261016b57610605610f04565b5f73ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6106976107f2565b165f526002602052602060ff60405f2054166040519015158152f35b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6106e16107f2565b6106e9610f04565b167fffffffffffffffffffffffff000000000000000000000000000000000000000060045416176004555f80f35b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6107456107f2565b165f526003602052602060ff60405f2054166040519015158152f35b3461016b5773ffffffffffffffffffffffffffffffffffffffff7fef81a9943b96c8df4ef243401c9bf5159146166211356898b52d382086168d9260206107a736610836565b93906107b1610f04565b1692835f52600282526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361016b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361016b57565b600319604091011261016b5760043573ffffffffffffffffffffffffffffffffffffffff8116810361016b5790602435801515810361016b5790565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761048057604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b156108fe5750565b61093c906040519182917f08c379a00000000000000000000000000000000000000000000000000000000083526020600484015260248301906108b3565b0390fd5b9081602091031261016b575190565b600492959373ffffffffffffffffffffffffffffffffffffffff821696875f52600160205260ff60405f205416916109bf6040938451906109908683610872565b600282527f333100000000000000000000000000000000000000000000000000000000000060208301526108f6565b602073ffffffffffffffffffffffffffffffffffffffff8316998a5f5260028252610a2560ff865f2054168651906109f78883610872565b600282527f3332000000000000000000000000000000000000000000000000000000000000858301526108f6565b73ffffffffffffffffffffffffffffffffffffffff87165f5260038252610a8760ff865f205416865190610a598883610872565b600282527f3439000000000000000000000000000000000000000000000000000000000000858301526108f6565b8451978880927f38d52e0f0000000000000000000000000000000000000000000000000000000082525afa958615610dac575f96610eb3575b508251917f70a082310000000000000000000000000000000000000000000000000000000083523060048401526020836024818d5afa928315610ea9575f93610e75575b50610b5784517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015283606482015260648152610b51608482610872565b8b6111f5565b8973ffffffffffffffffffffffffffffffffffffffff881614610e655750610b989073ffffffffffffffffffffffffffffffffffffffff600454168a6110db565b73ffffffffffffffffffffffffffffffffffffffff60045416825180977f29adffad00000000000000000000000000000000000000000000000000000000825284600483015260a061010483019173ffffffffffffffffffffffffffffffffffffffff815116604485015273ffffffffffffffffffffffffffffffffffffffff6020820151166064850152868101516084850152606081015160a4850152608081015160c485015201519060c060e4840152815180915261012483019060206101248260051b8601019301915f905b828210610df4575050505091815f8160209530602483015203925af1958615610dea575f96610db6575b508151977f70a082310000000000000000000000000000000000000000000000000000000089523060048a0152602089602481845afa988915610dac575f99610d78575b5081890391898311610d4b57610cf39903610cf5575b505050610f50565b565b91517fa9059cbb000000000000000000000000000000000000000000000000000000006020820152336024820152604480820192909252908152610d4391610d3e606483610872565b6111f5565b5f8080610ceb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9098506020813d602011610da4575b81610d9460209383610872565b8101031261016b5751975f610cd5565b3d9150610d87565b83513d5f823e3d90fd5b9095506020813d602011610de2575b81610dd260209383610872565b8101031261016b5751945f610c91565b3d9150610dc5565b82513d5f823e3d90fd5b91936020610e55827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc60019597998495030186528b838a5173ffffffffffffffffffffffffffffffffffffffff8151168452015191818582015201906108b3565b9601920192018b94939192610c67565b955095505050610cf39550610f50565b9092506020813d602011610ea1575b81610e9160209383610872565b8101031261016b5751915f610b04565b3d9150610e84565b84513d5f823e3d90fd5b9095506020813d602011610efc575b81610ecf60209383610872565b8101031261016b575173ffffffffffffffffffffffffffffffffffffffff8116810361016b57945f610ac0565b3d9150610ec2565b73ffffffffffffffffffffffffffffffffffffffff5f54163303610f2457565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b91909392935f9360028110156110ae5761101d57508184610f8e73ffffffffffffffffffffffffffffffffffffffff9660209588610fd296166110db565b6040517f6e553f6500000000000000000000000000000000000000000000000000000000815260048101919091523360248201529485928391869183906044820190565b0393165af19081156110115750610fe65750565b6110079060203d60201161100a575b610fff8183610872565b810190610940565b50565b503d610ff5565b604051903d90823e3d90fd5b915073ffffffffffffffffffffffffffffffffffffffff925083828461104393166110db565b16803b1561016b576040517f29344f0800000000000000000000000000000000000000000000000000000000815260048101929092523360248301525f908290604490829084905af180156110a3576110995750565b5f610cf391610872565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6040517f095ea7b300000000000000000000000000000000000000000000000000000000602080830191825273ffffffffffffffffffffffffffffffffffffffff85166024840152604480840196909652948252929390925f90611140606486610872565b84519082855af15f513d826111c3575b50501561115c57505050565b610d3e610cf39373ffffffffffffffffffffffffffffffffffffffff604051917f095ea7b30000000000000000000000000000000000000000000000000000000060208401521660248201525f6044820152604481526111bd606482610872565b826111f5565b9091506111ed575073ffffffffffffffffffffffffffffffffffffffff81163b15155b5f80611150565b6001146111e6565b905f602091828151910182855af1156110a3575f513d611273575073ffffffffffffffffffffffffffffffffffffffff81163b155b6112315750565b73ffffffffffffffffffffffffffffffffffffffff907f5274afe7000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b6001141561122a56fea26469706673582212203d9c4b6eebcc8ce872cc1748f924bf0bb16c1dec35b38534d4d46a9a637f7c3664736f6c634300081b0033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004c582a0d5552a906c48d9ba647519570c69ba09500000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b402e0479579b00f9dafc0526234bbc4583920b400000000000000000000000000000000000000000000000000000000000000030000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b3000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000010000000000000000000000001eda32cec481f92e99fea8bf74a9c98c589d498d

Deployed Bytecode

0x60806040526004361015610011575f80fd5b5f3560e01c80630ffb1d8b1461076157806338fcfe7a146107175780634133f100146106b357806368c4ac2614610669578063715018a6146105ed578063750b1537146105ba5780638da5cb5b14610588578063b5c3d68d146104f7578063b71b73c3146104ad578063e0f8a1d21461020b578063e6e66c681461016f5763f2fde38b1461009d575f80fd5b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6100cb6107f2565b6100d3610f04565b16801561013f5773ffffffffffffffffffffffffffffffffffffffff5f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b5f80fd5b3461016b5773ffffffffffffffffffffffffffffffffffffffff7f9652e0d255e1984241157f0e5f65c662604b493e181fde308bc5b66d116d63fe60206101b536610836565b93906101bf610f04565b1692835f52600182526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6040519015158152a2005b3461016b5760c060031936011261016b576102246107f2565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361016b576044359073ffffffffffffffffffffffffffffffffffffffff8216820361016b5760843590600282101561016b5760a4359267ffffffffffffffff841161016b5760c0600319853603011261016b576040519360c0850185811067ffffffffffffffff821117610480576040526102be81600401610815565b85526102cc60248201610815565b602086015260448101356040860152606481013560608601526084810135608086015260a48101359067ffffffffffffffff821161016b5701943660238701121561016b57600486013567ffffffffffffffff8111610480578060051b966040519161033b60208a0184610872565b8252602082019781016024019036821161016b5760248101985b828a1061037457505050610372965060a08601526064359261094f565b005b893567ffffffffffffffff811161016b576004908301019060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0833603011261016b57604051916040830183811067ffffffffffffffff821117610480576040526103e260208201610815565b8352604081013567ffffffffffffffff811161016b5760209101019036601f8301121561016b5781359267ffffffffffffffff841161048057604051610450601f86017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200182610872565b848152366020868601011161016b575f602086819782809801838601378301015283820152815201990198610355565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6104db6107f2565b165f526001602052602060ff60405f2054166040519015158152f35b3461016b5773ffffffffffffffffffffffffffffffffffffffff7fa97560bd93588927d79d92af36657c64b68481447620f4696e4fe9bf7ce2439a602061053d36610836565b9390610547610f04565b1692835f52600382526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b3461016b575f60031936011261016b57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461016b575f60031936011261016b57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b3461016b575f60031936011261016b57610605610f04565b5f73ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6106976107f2565b165f526002602052602060ff60405f2054166040519015158152f35b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6106e16107f2565b6106e9610f04565b167fffffffffffffffffffffffff000000000000000000000000000000000000000060045416176004555f80f35b3461016b57602060031936011261016b5773ffffffffffffffffffffffffffffffffffffffff6107456107f2565b165f526003602052602060ff60405f2054166040519015158152f35b3461016b5773ffffffffffffffffffffffffffffffffffffffff7fef81a9943b96c8df4ef243401c9bf5159146166211356898b52d382086168d9260206107a736610836565b93906107b1610f04565b1692835f52600282526102008160405f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361016b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361016b57565b600319604091011261016b5760043573ffffffffffffffffffffffffffffffffffffffff8116810361016b5790602435801515810361016b5790565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761048057604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b156108fe5750565b61093c906040519182917f08c379a00000000000000000000000000000000000000000000000000000000083526020600484015260248301906108b3565b0390fd5b9081602091031261016b575190565b600492959373ffffffffffffffffffffffffffffffffffffffff821696875f52600160205260ff60405f205416916109bf6040938451906109908683610872565b600282527f333100000000000000000000000000000000000000000000000000000000000060208301526108f6565b602073ffffffffffffffffffffffffffffffffffffffff8316998a5f5260028252610a2560ff865f2054168651906109f78883610872565b600282527f3332000000000000000000000000000000000000000000000000000000000000858301526108f6565b73ffffffffffffffffffffffffffffffffffffffff87165f5260038252610a8760ff865f205416865190610a598883610872565b600282527f3439000000000000000000000000000000000000000000000000000000000000858301526108f6565b8451978880927f38d52e0f0000000000000000000000000000000000000000000000000000000082525afa958615610dac575f96610eb3575b508251917f70a082310000000000000000000000000000000000000000000000000000000083523060048401526020836024818d5afa928315610ea9575f93610e75575b50610b5784517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015283606482015260648152610b51608482610872565b8b6111f5565b8973ffffffffffffffffffffffffffffffffffffffff881614610e655750610b989073ffffffffffffffffffffffffffffffffffffffff600454168a6110db565b73ffffffffffffffffffffffffffffffffffffffff60045416825180977f29adffad00000000000000000000000000000000000000000000000000000000825284600483015260a061010483019173ffffffffffffffffffffffffffffffffffffffff815116604485015273ffffffffffffffffffffffffffffffffffffffff6020820151166064850152868101516084850152606081015160a4850152608081015160c485015201519060c060e4840152815180915261012483019060206101248260051b8601019301915f905b828210610df4575050505091815f8160209530602483015203925af1958615610dea575f96610db6575b508151977f70a082310000000000000000000000000000000000000000000000000000000089523060048a0152602089602481845afa988915610dac575f99610d78575b5081890391898311610d4b57610cf39903610cf5575b505050610f50565b565b91517fa9059cbb000000000000000000000000000000000000000000000000000000006020820152336024820152604480820192909252908152610d4391610d3e606483610872565b6111f5565b5f8080610ceb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9098506020813d602011610da4575b81610d9460209383610872565b8101031261016b5751975f610cd5565b3d9150610d87565b83513d5f823e3d90fd5b9095506020813d602011610de2575b81610dd260209383610872565b8101031261016b5751945f610c91565b3d9150610dc5565b82513d5f823e3d90fd5b91936020610e55827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc60019597998495030186528b838a5173ffffffffffffffffffffffffffffffffffffffff8151168452015191818582015201906108b3565b9601920192018b94939192610c67565b955095505050610cf39550610f50565b9092506020813d602011610ea1575b81610e9160209383610872565b8101031261016b5751915f610b04565b3d9150610e84565b84513d5f823e3d90fd5b9095506020813d602011610efc575b81610ecf60209383610872565b8101031261016b575173ffffffffffffffffffffffffffffffffffffffff8116810361016b57945f610ac0565b3d9150610ec2565b73ffffffffffffffffffffffffffffffffffffffff5f54163303610f2457565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b91909392935f9360028110156110ae5761101d57508184610f8e73ffffffffffffffffffffffffffffffffffffffff9660209588610fd296166110db565b6040517f6e553f6500000000000000000000000000000000000000000000000000000000815260048101919091523360248201529485928391869183906044820190565b0393165af19081156110115750610fe65750565b6110079060203d60201161100a575b610fff8183610872565b810190610940565b50565b503d610ff5565b604051903d90823e3d90fd5b915073ffffffffffffffffffffffffffffffffffffffff925083828461104393166110db565b16803b1561016b576040517f29344f0800000000000000000000000000000000000000000000000000000000815260048101929092523360248301525f908290604490829084905af180156110a3576110995750565b5f610cf391610872565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6040517f095ea7b300000000000000000000000000000000000000000000000000000000602080830191825273ffffffffffffffffffffffffffffffffffffffff85166024840152604480840196909652948252929390925f90611140606486610872565b84519082855af15f513d826111c3575b50501561115c57505050565b610d3e610cf39373ffffffffffffffffffffffffffffffffffffffff604051917f095ea7b30000000000000000000000000000000000000000000000000000000060208401521660248201525f6044820152604481526111bd606482610872565b826111f5565b9091506111ed575073ffffffffffffffffffffffffffffffffffffffff81163b15155b5f80611150565b6001146111e6565b905f602091828151910182855af1156110a3575f513d611273575073ffffffffffffffffffffffffffffffffffffffff81163b155b6112315750565b73ffffffffffffffffffffffffffffffffffffffff907f5274afe7000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b6001141561122a56fea26469706673582212203d9c4b6eebcc8ce872cc1748f924bf0bb16c1dec35b38534d4d46a9a637f7c3664736f6c634300081b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004c582a0d5552a906c48d9ba647519570c69ba09500000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b402e0479579b00f9dafc0526234bbc4583920b400000000000000000000000000000000000000000000000000000000000000030000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b3000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000010000000000000000000000001eda32cec481f92e99fea8bf74a9c98c589d498d

-----Decoded View---------------
Arg [0] : _supportedVaults (address[]): 0xB402e0479579b00f9DAfc0526234BBC4583920B4
Arg [1] : _supportedTokens (address[]): 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3,0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [2] : _universalDexModule (address): 0x4c582A0d5552a906C48D9ba647519570C69bA095
Arg [3] : _supportedDepositManagers (address[]): 0x1EDA32cec481f92E99fEa8bf74A9c98C589d498d

-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000004c582a0d5552a906c48d9ba647519570c69ba095
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 000000000000000000000000b402e0479579b00f9dafc0526234bbc4583920b4
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b3
Arg [8] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [9] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [11] : 0000000000000000000000001eda32cec481f92e99fea8bf74a9c98c589d498d


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.