S Price: $0.453184 (+3.17%)

Contract

0x4f51FbD2161FC5e41295b866cB42A08e7eA39a25

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EscrowedCollateralPerspective

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 20000 runs

Other Settings:
cancun EvmVersion
File 1 of 11 : EscrowedCollateralPerspective.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.24;

import {GenericFactory} from "evk/GenericFactory/GenericFactory.sol";
import {IEVault} from "evk/EVault/IEVault.sol";
import "evk/EVault/shared/Constants.sol";

import {BasePerspective} from "../implementation/BasePerspective.sol";

/// @title EscrowedCollateralPerspective
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A contract that verifies whether a vault has properties of an escrow vault. It allows only one escrow vault
/// per asset if the vault has no supply cap configured.
contract EscrowedCollateralPerspective is BasePerspective {
    /// @notice A mapping to look up the vault associated with a given asset.
    mapping(address => address) public singletonLookup;

    /// @notice Creates a new EscrowedCollateralPerspective instance.
    /// @param vaultFactory_ The address of the GenericFactory contract.
    constructor(address vaultFactory_) BasePerspective(vaultFactory_) {}

    /// @inheritdoc BasePerspective
    function name() public pure virtual override returns (string memory) {
        return "Escrowed Collateral Perspective";
    }

    /// @inheritdoc BasePerspective
    function perspectiveVerifyInternal(address vault) internal override {
        // the vault must be deployed by recognized factory
        testProperty(vaultFactory.isProxy(vault), ERROR__FACTORY);

        // escrow vaults must be upgradeable
        testProperty(vaultFactory.getProxyConfig(vault).upgradeable, ERROR__UPGRADABILITY);

        // escrow vaults must not be nested
        address asset = IEVault(vault).asset();
        testProperty(!vaultFactory.isProxy(asset), ERROR__NESTING);

        // escrow vaults must not have an oracle or unit of account
        testProperty(IEVault(vault).oracle() == address(0), ERROR__ORACLE_INVALID_ROUTER);
        testProperty(IEVault(vault).unitOfAccount() == address(0), ERROR__UNIT_OF_ACCOUNT);

        // verify vault configuration at the governance level.
        // escrow vaults must not have a governor admin, fee receiver, or interest rate model
        testProperty(IEVault(vault).governorAdmin() == address(0), ERROR__GOVERNOR);
        testProperty(IEVault(vault).feeReceiver() == address(0), ERROR__FEE_RECEIVER);
        testProperty(IEVault(vault).interestRateModel() == address(0), ERROR__INTEREST_RATE_MODEL);

        {
            // escrow vaults must be singletons if they do not have a supply cap configured
            (uint32 supplyCap, uint32 borrowCap) = IEVault(vault).caps();
            testProperty(supplyCap != 0 || singletonLookup[asset] == address(0), ERROR__SINGLETON);

            // escrow vaults must not have borrow cap
            testProperty(borrowCap == 0, ERROR__BORROW_CAP);

            // escrow vaults must not have a hook target nor any operations disabled
            (address hookTarget, uint32 hookedOps) = IEVault(vault).hookConfig();
            testProperty(hookTarget == address(0), ERROR__HOOK_TARGET);
            testProperty(hookedOps == 0, ERROR__HOOKED_OPS);
        }

        // escrow vaults must not have any config flags set
        testProperty(IEVault(vault).configFlags() == 0, ERROR__CONFIG_FLAGS);

        // escrow vaults must neither have liquidation discount nor liquidation cool off time
        testProperty(IEVault(vault).maxLiquidationDiscount() == 0, ERROR__LIQUIDATION_DISCOUNT);
        testProperty(IEVault(vault).liquidationCoolOffTime() == 0, ERROR__LIQUIDATION_COOL_OFF_TIME);

        // escrow vaults must not have any collateral set up
        testProperty(IEVault(vault).LTVList().length == 0, ERROR__LTV_COLLATERAL_CONFIG_LENGTH);

        // store in mapping so that, if the vault has no supply cap, one escrow vault per asset can be achieved
        if (singletonLookup[asset] == address(0)) {
            singletonLookup[asset] = vault;
        }
    }
}

File 2 of 11 : GenericFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

import {BeaconProxy} from "./BeaconProxy.sol";
import {MetaProxyDeployer} from "./MetaProxyDeployer.sol";

/// @title IComponent
/// @notice Minimal interface which must be implemented by the contract deployed by the factory
interface IComponent {
    /// @notice Function replacing the constructor in proxied contracts
    /// @param creator The new contract's creator address
    function initialize(address creator) external;
}

/// @title GenericFactory
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice The factory allows permissionless creation of upgradeable or non-upgradeable proxy contracts and serves as a
/// beacon for the upgradeable ones
contract GenericFactory is MetaProxyDeployer {
    // Constants

    uint256 internal constant REENTRANCYLOCK__UNLOCKED = 1;
    uint256 internal constant REENTRANCYLOCK__LOCKED = 2;

    // State

    /// @title ProxyConfig
    /// @notice This struct is used to store the configuration of a proxy deployed by the factory
    struct ProxyConfig {
        // If true, proxy is an instance of the BeaconProxy
        bool upgradeable;
        // Address of the implementation contract
        // May be an out-of-date value, if upgradeable (handled by getProxyConfig)
        address implementation;
        // The metadata attached to every call passing through the proxy
        bytes trailingData;
    }

    uint256 private reentrancyLock;

    /// @notice Address of the account authorized to upgrade the implementation contract
    address public upgradeAdmin;
    /// @notice Address of the implementation contract, which the deployed proxies will delegate-call to
    /// @dev The contract must implement the `IComponent` interface
    address public implementation;
    /// @notice A lookup for configurations of the proxy contracts deployed by the factory
    mapping(address proxy => ProxyConfig) internal proxyLookup;
    /// @notice An array of addresses of all the proxies deployed by the factory
    address[] public proxyList;

    // Events

    /// @notice The factory is created
    event Genesis();

    /// @notice A new proxy is created
    /// @param proxy Address of the new proxy
    /// @param upgradeable If true, proxy is an instance of the BeaconProxy. If false, the proxy is a minimal meta proxy
    /// @param implementation Address of the implementation contract, at the time the proxy was deployed
    /// @param trailingData The metadata that will be attached to every call passing through the proxy
    event ProxyCreated(address indexed proxy, bool upgradeable, address implementation, bytes trailingData);

    /// @notice Set a new implementation contract. All the BeaconProxies are upgraded to the new logic
    /// @param newImplementation Address of the new implementation contract
    event SetImplementation(address indexed newImplementation);

    /// @notice Set a new upgrade admin
    /// @param newUpgradeAdmin Address of the new admin
    event SetUpgradeAdmin(address indexed newUpgradeAdmin);

    // Errors

    error E_Reentrancy();
    error E_Unauthorized();
    error E_Implementation();
    error E_BadAddress();
    error E_BadQuery();

    // Modifiers

    modifier nonReentrant() {
        if (reentrancyLock == REENTRANCYLOCK__LOCKED) revert E_Reentrancy();

        reentrancyLock = REENTRANCYLOCK__LOCKED;
        _;
        reentrancyLock = REENTRANCYLOCK__UNLOCKED;
    }

    modifier adminOnly() {
        if (msg.sender != upgradeAdmin) revert E_Unauthorized();
        _;
    }

    constructor(address admin) {
        emit Genesis();

        if (admin == address(0)) revert E_BadAddress();

        reentrancyLock = REENTRANCYLOCK__UNLOCKED;

        upgradeAdmin = admin;

        emit SetUpgradeAdmin(admin);
    }

    /// @notice A permissionless funtion to deploy new proxies
    /// @param desiredImplementation Address of the implementation contract expected to be registered in the factory
    /// during proxy creation
    /// @param upgradeable If true, the proxy will be an instance of the BeaconProxy. If false, a minimal meta proxy
    /// will be deployed
    /// @param trailingData Metadata to be attached to every call passing through the new proxy
    /// @return The address of the new proxy
    /// @dev The desired implementation serves as a protection against (unintentional) front-running of upgrades
    function createProxy(address desiredImplementation, bool upgradeable, bytes memory trailingData)
        external
        nonReentrant
        returns (address)
    {
        address _implementation = implementation;
        if (desiredImplementation == address(0)) desiredImplementation = _implementation;

        if (desiredImplementation == address(0) || desiredImplementation != _implementation) revert E_Implementation();

        // The provided trailing data is prefixed with 4 zero bytes to avoid potential selector clashing in case the
        // proxy is called with empty calldata.
        bytes memory prefixTrailingData = abi.encodePacked(bytes4(0), trailingData);
        address proxy;

        if (upgradeable) {
            proxy = address(new BeaconProxy(prefixTrailingData));
        } else {
            proxy = deployMetaProxy(desiredImplementation, prefixTrailingData);
        }

        proxyLookup[proxy] =
            ProxyConfig({upgradeable: upgradeable, implementation: desiredImplementation, trailingData: trailingData});

        proxyList.push(proxy);

        IComponent(proxy).initialize(msg.sender);

        emit ProxyCreated(proxy, upgradeable, desiredImplementation, trailingData);

        return proxy;
    }

    // EVault beacon upgrade

    /// @notice Set a new implementation contract
    /// @param newImplementation Address of the new implementation contract
    /// @dev Upgrades all existing BeaconProxies to the new logic immediately
    function setImplementation(address newImplementation) external nonReentrant adminOnly {
        if (newImplementation.code.length == 0) revert E_BadAddress();
        implementation = newImplementation;
        emit SetImplementation(newImplementation);
    }

    // Admin role

    /// @notice Transfer admin rights to a new address
    /// @param newUpgradeAdmin Address of the new admin
    /// @dev For creating non upgradeable factories, or to finalize all upgradeable proxies to current implementation,
    /// @dev set the admin to zero address.
    /// @dev If setting to address zero, make sure the implementation contract is already set
    function setUpgradeAdmin(address newUpgradeAdmin) external nonReentrant adminOnly {
        upgradeAdmin = newUpgradeAdmin;
        emit SetUpgradeAdmin(newUpgradeAdmin);
    }

    // Proxy getters

    /// @notice Get current proxy configuration
    /// @param proxy Address of the proxy to query
    /// @return config The proxy's configuration, including current implementation
    function getProxyConfig(address proxy) external view returns (ProxyConfig memory config) {
        config = proxyLookup[proxy];
        if (config.upgradeable) config.implementation = implementation;
    }

    /// @notice Check if an address is a proxy deployed with this factory
    /// @param proxy Address to check
    /// @return True if the address is a proxy
    function isProxy(address proxy) external view returns (bool) {
        return proxyLookup[proxy].implementation != address(0);
    }

    /// @notice Fetch the length of the deployed proxies list
    /// @return The length of the proxy list array
    function getProxyListLength() external view returns (uint256) {
        return proxyList.length;
    }

    /// @notice Get a slice of the deployed proxies array
    /// @param start Start index of the slice
    /// @param end End index of the slice
    /// @return list An array containing the slice of the proxy list
    function getProxyListSlice(uint256 start, uint256 end) external view returns (address[] memory list) {
        if (end == type(uint256).max) end = proxyList.length;
        if (end < start || end > proxyList.length) revert E_BadQuery();

        list = new address[](end - start);
        for (uint256 i; i < end - start; ++i) {
            list[i] = proxyList[start + i];
        }
    }
}

File 3 of 11 : IEVault.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.8.0;

import {IVault as IEVCVault} from "ethereum-vault-connector/interfaces/IVault.sol";

// Full interface of EVault and all it's modules

/// @title IInitialize
/// @notice Interface of the initialization module of EVault
interface IInitialize {
    /// @notice Initialization of the newly deployed proxy contract
    /// @param proxyCreator Account which created the proxy or should be the initial governor
    function initialize(address proxyCreator) external;
}

/// @title IERC20
/// @notice Interface of the EVault's Initialize module
interface IERC20 {
    /// @notice Vault share token (eToken) name, ie "Euler Vault: DAI"
    /// @return The name of the eToken
    function name() external view returns (string memory);

    /// @notice Vault share token (eToken) symbol, ie "eDAI"
    /// @return The symbol of the eToken
    function symbol() external view returns (string memory);

    /// @notice Decimals, the same as the asset's or 18 if the asset doesn't implement `decimals()`
    /// @return The decimals of the eToken
    function decimals() external view returns (uint8);

    /// @notice Sum of all eToken balances
    /// @return The total supply of the eToken
    function totalSupply() external view returns (uint256);

    /// @notice Balance of a particular account, in eTokens
    /// @param account Address to query
    /// @return The balance of the account
    function balanceOf(address account) external view returns (uint256);

    /// @notice Retrieve the current allowance
    /// @param holder The account holding the eTokens
    /// @param spender Trusted address
    /// @return The allowance from holder for spender
    function allowance(address holder, address spender) external view returns (uint256);

    /// @notice Transfer eTokens to another address
    /// @param to Recipient account
    /// @param amount In shares.
    /// @return True if transfer succeeded
    function transfer(address to, uint256 amount) external returns (bool);

    /// @notice Transfer eTokens from one address to another
    /// @param from This address must've approved the to address
    /// @param to Recipient account
    /// @param amount In shares
    /// @return True if transfer succeeded
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    /// @notice Allow spender to access an amount of your eTokens
    /// @param spender Trusted address
    /// @param amount Use max uint for "infinite" allowance
    /// @return True if approval succeeded
    function approve(address spender, uint256 amount) external returns (bool);
}

/// @title IToken
/// @notice Interface of the EVault's Token module
interface IToken is IERC20 {
    /// @notice Transfer the full eToken balance of an address to another
    /// @param from This address must've approved the to address
    /// @param to Recipient account
    /// @return True if transfer succeeded
    function transferFromMax(address from, address to) external returns (bool);
}

/// @title IERC4626
/// @notice Interface of an ERC4626 vault
interface IERC4626 {
    /// @notice Vault's underlying asset
    /// @return The vault's underlying asset
    function asset() external view returns (address);

    /// @notice Total amount of managed assets, cash and borrows
    /// @return The total amount of assets
    function totalAssets() external view returns (uint256);

    /// @notice Calculate amount of assets corresponding to the requested shares amount
    /// @param shares Amount of shares to convert
    /// @return The amount of assets
    function convertToAssets(uint256 shares) external view returns (uint256);

    /// @notice Calculate amount of shares corresponding to the requested assets amount
    /// @param assets Amount of assets to convert
    /// @return The amount of shares
    function convertToShares(uint256 assets) external view returns (uint256);

    /// @notice Fetch the maximum amount of assets a user can deposit
    /// @param account Address to query
    /// @return The max amount of assets the account can deposit
    function maxDeposit(address account) external view returns (uint256);

    /// @notice Calculate an amount of shares that would be created by depositing assets
    /// @param assets Amount of assets deposited
    /// @return Amount of shares received
    function previewDeposit(uint256 assets) external view returns (uint256);

    /// @notice Fetch the maximum amount of shares a user can mint
    /// @param account Address to query
    /// @return The max amount of shares the account can mint
    function maxMint(address account) external view returns (uint256);

    /// @notice Calculate an amount of assets that would be required to mint requested amount of shares
    /// @param shares Amount of shares to be minted
    /// @return Required amount of assets
    function previewMint(uint256 shares) external view returns (uint256);

    /// @notice Fetch the maximum amount of assets a user is allowed to withdraw
    /// @param owner Account holding the shares
    /// @return The maximum amount of assets the owner is allowed to withdraw
    function maxWithdraw(address owner) external view returns (uint256);

    /// @notice Calculate the amount of shares that will be burned when withdrawing requested amount of assets
    /// @param assets Amount of assets withdrawn
    /// @return Amount of shares burned
    function previewWithdraw(uint256 assets) external view returns (uint256);

    /// @notice Fetch the maximum amount of shares a user is allowed to redeem for assets
    /// @param owner Account holding the shares
    /// @return The maximum amount of shares the owner is allowed to redeem
    function maxRedeem(address owner) external view returns (uint256);

    /// @notice Calculate the amount of assets that will be transferred when redeeming requested amount of shares
    /// @param shares Amount of shares redeemed
    /// @return Amount of assets transferred
    function previewRedeem(uint256 shares) external view returns (uint256);

    /// @notice Transfer requested amount of underlying tokens from sender to the vault pool in return for shares
    /// @param amount Amount of assets to deposit (use max uint256 for full underlying token balance)
    /// @param receiver An account to receive the shares
    /// @return Amount of shares minted
    /// @dev Deposit will round down the amount of assets that are converted to shares. To prevent losses consider using
    /// mint instead.
    function deposit(uint256 amount, address receiver) external returns (uint256);

    /// @notice Transfer underlying tokens from sender to the vault pool in return for requested amount of shares
    /// @param amount Amount of shares to be minted
    /// @param receiver An account to receive the shares
    /// @return Amount of assets deposited
    function mint(uint256 amount, address receiver) external returns (uint256);

    /// @notice Transfer requested amount of underlying tokens from the vault and decrease account's shares balance
    /// @param amount Amount of assets to withdraw
    /// @param receiver Account to receive the withdrawn assets
    /// @param owner Account holding the shares to burn
    /// @return Amount of shares burned
    function withdraw(uint256 amount, address receiver, address owner) external returns (uint256);

    /// @notice Burn requested shares and transfer corresponding underlying tokens from the vault to the receiver
    /// @param amount Amount of shares to burn (use max uint256 to burn full owner balance)
    /// @param receiver Account to receive the withdrawn assets
    /// @param owner Account holding the shares to burn.
    /// @return Amount of assets transferred
    function redeem(uint256 amount, address receiver, address owner) external returns (uint256);
}

/// @title IVault
/// @notice Interface of the EVault's Vault module
interface IVault is IERC4626 {
    /// @notice Balance of the fees accumulator, in shares
    /// @return The accumulated fees in shares
    function accumulatedFees() external view returns (uint256);

    /// @notice Balance of the fees accumulator, in underlying units
    /// @return The accumulated fees in asset units
    function accumulatedFeesAssets() external view returns (uint256);

    /// @notice Address of the original vault creator
    /// @return The address of the creator
    function creator() external view returns (address);

    /// @notice Creates shares for the receiver, from excess asset balances of the vault (not accounted for in `cash`)
    /// @param amount Amount of assets to claim (use max uint256 to claim all available assets)
    /// @param receiver An account to receive the shares
    /// @return Amount of shares minted
    /// @dev Could be used as an alternative deposit flow in certain scenarios. E.g. swap directly to the vault, call
    /// `skim` to claim deposit.
    function skim(uint256 amount, address receiver) external returns (uint256);
}

/// @title IBorrowing
/// @notice Interface of the EVault's Borrowing module
interface IBorrowing {
    /// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued)
    /// @return The total borrows in asset units
    function totalBorrows() external view returns (uint256);

    /// @notice Sum of all outstanding debts, in underlying units scaled up by shifting
    /// INTERNAL_DEBT_PRECISION_SHIFT bits
    /// @return The total borrows in internal debt precision
    function totalBorrowsExact() external view returns (uint256);

    /// @notice Balance of vault assets as tracked by deposits/withdrawals and borrows/repays
    /// @return The amount of assets the vault tracks as current direct holdings
    function cash() external view returns (uint256);

    /// @notice Debt owed by a particular account, in underlying units
    /// @param account Address to query
    /// @return The debt of the account in asset units
    function debtOf(address account) external view returns (uint256);

    /// @notice Debt owed by a particular account, in underlying units scaled up by shifting
    /// INTERNAL_DEBT_PRECISION_SHIFT bits
    /// @param account Address to query
    /// @return The debt of the account in internal precision
    function debtOfExact(address account) external view returns (uint256);

    /// @notice Retrieves the current interest rate for an asset
    /// @return The interest rate in yield-per-second, scaled by 10**27
    function interestRate() external view returns (uint256);

    /// @notice Retrieves the current interest rate accumulator for an asset
    /// @return An opaque accumulator that increases as interest is accrued
    function interestAccumulator() external view returns (uint256);

    /// @notice Returns an address of the sidecar DToken
    /// @return The address of the DToken
    function dToken() external view returns (address);

    /// @notice Transfer underlying tokens from the vault to the sender, and increase sender's debt
    /// @param amount Amount of assets to borrow (use max uint256 for all available tokens)
    /// @param receiver Account receiving the borrowed tokens
    /// @return Amount of assets borrowed
    function borrow(uint256 amount, address receiver) external returns (uint256);

    /// @notice Transfer underlying tokens from the sender to the vault, and decrease receiver's debt
    /// @param amount Amount of debt to repay in assets (use max uint256 for full debt)
    /// @param receiver Account holding the debt to be repaid
    /// @return Amount of assets repaid
    function repay(uint256 amount, address receiver) external returns (uint256);

    /// @notice Pay off liability with shares ("self-repay")
    /// @param amount In asset units (use max uint256 to repay the debt in full or up to the available deposit)
    /// @param receiver Account to remove debt from by burning sender's shares
    /// @return shares Amount of shares burned
    /// @return debt Amount of debt removed in assets
    /// @dev Equivalent to withdrawing and repaying, but no assets are needed to be present in the vault
    /// @dev Contrary to a regular `repay`, if account is unhealthy, the repay amount must bring the account back to
    /// health, or the operation will revert during account status check
    function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt);

    /// @notice Take over debt from another account
    /// @param amount Amount of debt in asset units (use max uint256 for all the account's debt)
    /// @param from Account to pull the debt from
    /// @dev Due to internal debt precision accounting, the liability reported on either or both accounts after
    /// calling `pullDebt` may not match the `amount` requested precisely
    function pullDebt(uint256 amount, address from) external;

    /// @notice Request a flash-loan. A onFlashLoan() callback in msg.sender will be invoked, which must repay the loan
    /// to the main Euler address prior to returning.
    /// @param amount In asset units
    /// @param data Passed through to the onFlashLoan() callback, so contracts don't need to store transient data in
    /// storage
    function flashLoan(uint256 amount, bytes calldata data) external;

    /// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs
    /// vault status
    function touch() external;
}

/// @title ILiquidation
/// @notice Interface of the EVault's Liquidation module
interface ILiquidation {
    /// @notice Checks to see if a liquidation would be profitable, without actually doing anything
    /// @param liquidator Address that will initiate the liquidation
    /// @param violator Address that may be in collateral violation
    /// @param collateral Collateral which is to be seized
    /// @return maxRepay Max amount of debt that can be repaid, in asset units
    /// @return maxYield Yield in collateral corresponding to max allowed amount of debt to be repaid, in collateral
    /// balance (shares for vaults)
    function checkLiquidation(address liquidator, address violator, address collateral)
        external
        view
        returns (uint256 maxRepay, uint256 maxYield);

    /// @notice Attempts to perform a liquidation
    /// @param violator Address that may be in collateral violation
    /// @param collateral Collateral which is to be seized
    /// @param repayAssets The amount of underlying debt to be transferred from violator to sender, in asset units (use
    /// max uint256 to repay the maximum possible amount). Meant as slippage check together with `minYieldBalance`
    /// @param minYieldBalance The minimum acceptable amount of collateral to be transferred from violator to sender, in
    /// collateral balance units (shares for vaults).  Meant as slippage check together with `repayAssets`
    /// @dev If `repayAssets` is set to max uint256 it is assumed the caller will perform their own slippage checks to
    /// make sure they are not taking on too much debt. This option is mainly meant for smart contract liquidators
    function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external;
}

/// @title IRiskManager
/// @notice Interface of the EVault's RiskManager module
interface IRiskManager is IEVCVault {
    /// @notice Retrieve account's total liquidity
    /// @param account Account holding debt in this vault
    /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status
    /// check mode, where different LTV values might apply.
    /// @return collateralValue Total risk adjusted value of all collaterals in unit of account
    /// @return liabilityValue Value of debt in unit of account
    function accountLiquidity(address account, bool liquidation)
        external
        view
        returns (uint256 collateralValue, uint256 liabilityValue);

    /// @notice Retrieve account's liquidity per collateral
    /// @param account Account holding debt in this vault
    /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status
    /// check mode, where different LTV values might apply.
    /// @return collaterals Array of collaterals enabled
    /// @return collateralValues Array of risk adjusted collateral values corresponding to items in collaterals array.
    /// In unit of account
    /// @return liabilityValue Value of debt in unit of account
    function accountLiquidityFull(address account, bool liquidation)
        external
        view
        returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue);

    /// @notice Release control of the account on EVC if no outstanding debt is present
    function disableController() external;

    /// @notice Checks the status of an account and reverts if account is not healthy
    /// @param account The address of the account to be checked
    /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when
    /// account status is valid, or revert otherwise.
    /// @dev Only callable by EVC during status checks
    function checkAccountStatus(address account, address[] calldata collaterals) external view returns (bytes4);

    /// @notice Checks the status of the vault and reverts if caps are exceeded
    /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when
    /// account status is valid, or revert otherwise.
    /// @dev Only callable by EVC during status checks
    function checkVaultStatus() external returns (bytes4);
}

/// @title IBalanceForwarder
/// @notice Interface of the EVault's BalanceForwarder module
interface IBalanceForwarder {
    /// @notice Retrieve the address of rewards contract, tracking changes in account's balances
    /// @return The balance tracker address
    function balanceTrackerAddress() external view returns (address);

    /// @notice Retrieves boolean indicating if the account opted in to forward balance changes to the rewards contract
    /// @param account Address to query
    /// @return True if balance forwarder is enabled
    function balanceForwarderEnabled(address account) external view returns (bool);

    /// @notice Enables balance forwarding for the authenticated account
    /// @dev Only the authenticated account can enable balance forwarding for itself
    /// @dev Should call the IBalanceTracker hook with the current account's balance
    function enableBalanceForwarder() external;

    /// @notice Disables balance forwarding for the authenticated account
    /// @dev Only the authenticated account can disable balance forwarding for itself
    /// @dev Should call the IBalanceTracker hook with the account's balance of 0
    function disableBalanceForwarder() external;
}

/// @title IGovernance
/// @notice Interface of the EVault's Governance module
interface IGovernance {
    /// @notice Retrieves the address of the governor
    /// @return The governor address
    function governorAdmin() external view returns (address);

    /// @notice Retrieves address of the governance fee receiver
    /// @return The fee receiver address
    function feeReceiver() external view returns (address);

    /// @notice Retrieves the interest fee in effect for the vault
    /// @return Amount of interest that is redirected as a fee, as a fraction scaled by 1e4
    function interestFee() external view returns (uint16);

    /// @notice Looks up an asset's currently configured interest rate model
    /// @return Address of the interest rate contract or address zero to indicate 0% interest
    function interestRateModel() external view returns (address);

    /// @notice Retrieves the ProtocolConfig address
    /// @return The protocol config address
    function protocolConfigAddress() external view returns (address);

    /// @notice Retrieves the protocol fee share
    /// @return A percentage share of fees accrued belonging to the protocol, in 1e4 scale
    function protocolFeeShare() external view returns (uint256);

    /// @notice Retrieves the address which will receive protocol's fees
    /// @notice The protocol fee receiver address
    function protocolFeeReceiver() external view returns (address);

    /// @notice Retrieves supply and borrow caps in AmountCap format
    /// @return supplyCap The supply cap in AmountCap format
    /// @return borrowCap The borrow cap in AmountCap format
    function caps() external view returns (uint16 supplyCap, uint16 borrowCap);

    /// @notice Retrieves the borrow LTV of the collateral, which is used to determine if the account is healthy during
    /// account status checks.
    /// @param collateral The address of the collateral to query
    /// @return Borrowing LTV in 1e4 scale
    function LTVBorrow(address collateral) external view returns (uint16);

    /// @notice Retrieves the current liquidation LTV, which is used to determine if the account is eligible for
    /// liquidation
    /// @param collateral The address of the collateral to query
    /// @return Liquidation LTV in 1e4 scale
    function LTVLiquidation(address collateral) external view returns (uint16);

    /// @notice Retrieves LTV configuration for the collateral
    /// @param collateral Collateral asset
    /// @return borrowLTV The current value of borrow LTV for originating positions
    /// @return liquidationLTV The value of fully converged liquidation LTV
    /// @return initialLiquidationLTV The initial value of the liquidation LTV, when the ramp began
    /// @return targetTimestamp The timestamp when the liquidation LTV is considered fully converged
    /// @return rampDuration The time it takes for the liquidation LTV to converge from the initial value to the fully
    /// converged value
    function LTVFull(address collateral)
        external
        view
        returns (
            uint16 borrowLTV,
            uint16 liquidationLTV,
            uint16 initialLiquidationLTV,
            uint48 targetTimestamp,
            uint32 rampDuration
        );

    /// @notice Retrieves a list of collaterals with configured LTVs
    /// @return List of asset collaterals
    /// @dev Returned assets could have the ltv disabled (set to zero)
    function LTVList() external view returns (address[] memory);

    /// @notice Retrieves the maximum liquidation discount
    /// @return The maximum liquidation discount in 1e4 scale
    /// @dev The default value, which is zero, is deliberately bad, as it means there would be no incentive to liquidate
    /// unhealthy users. The vault creator must take care to properly select the limit, given the underlying and
    /// collaterals used.
    function maxLiquidationDiscount() external view returns (uint16);

    /// @notice Retrieves liquidation cool-off time, which must elapse after successful account status check before
    /// account can be liquidated
    /// @return The liquidation cool off time in seconds
    function liquidationCoolOffTime() external view returns (uint16);

    /// @notice Retrieves a hook target and a bitmask indicating which operations call the hook target
    /// @return hookTarget Address of the hook target contract
    /// @return hookedOps Bitmask with operations that should call the hooks. See Constants.sol for a list of operations
    function hookConfig() external view returns (address hookTarget, uint32 hookedOps);

    /// @notice Retrieves a bitmask indicating enabled config flags
    /// @return Bitmask with config flags enabled
    function configFlags() external view returns (uint32);

    /// @notice Address of EthereumVaultConnector contract
    /// @return The EVC address
    function EVC() external view returns (address);

    /// @notice Retrieves a reference asset used for liquidity calculations
    /// @return The address of the reference asset
    function unitOfAccount() external view returns (address);

    /// @notice Retrieves the address of the oracle contract
    /// @return The address of the oracle
    function oracle() external view returns (address);

    /// @notice Retrieves the Permit2 contract address
    /// @return The address of the Permit2 contract
    function permit2Address() external view returns (address);

    /// @notice Splits accrued fees balance according to protocol fee share and transfers shares to the governor fee
    /// receiver and protocol fee receiver
    function convertFees() external;

    /// @notice Set a new governor address
    /// @param newGovernorAdmin The new governor address
    /// @dev Set to zero address to renounce privileges and make the vault non-governed
    function setGovernorAdmin(address newGovernorAdmin) external;

    /// @notice Set a new governor fee receiver address
    /// @param newFeeReceiver The new fee receiver address
    function setFeeReceiver(address newFeeReceiver) external;

    /// @notice Set a new LTV config
    /// @param collateral Address of collateral to set LTV for
    /// @param borrowLTV New borrow LTV, for assessing account's health during account status checks, in 1e4 scale
    /// @param liquidationLTV New liquidation LTV after ramp ends in 1e4 scale
    /// @param rampDuration Ramp duration in seconds
    function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external;

    /// @notice Set a new maximum liquidation discount
    /// @param newDiscount New maximum liquidation discount in 1e4 scale
    /// @dev If the discount is zero (the default), the liquidators will not be incentivized to liquidate unhealthy
    /// accounts
    function setMaxLiquidationDiscount(uint16 newDiscount) external;

    /// @notice Set a new liquidation cool off time, which must elapse after successful account status check before
    /// account can be liquidated
    /// @param newCoolOffTime The new liquidation cool off time in seconds
    /// @dev Setting cool off time to zero allows liquidating the account in the same block as the last successful
    /// account status check
    function setLiquidationCoolOffTime(uint16 newCoolOffTime) external;

    /// @notice Set a new interest rate model contract
    /// @param newModel The new IRM address
    /// @dev If the new model reverts, perhaps due to governor error, the vault will silently use a zero interest
    /// rate. Governor should make sure the new interest rates are computed as expected.
    function setInterestRateModel(address newModel) external;

    /// @notice Set a new hook target and a new bitmap indicating which operations should call the hook target.
    /// Operations are defined in Constants.sol.
    /// @param newHookTarget The new hook target address. Use address(0) to simply disable hooked operations
    /// @param newHookedOps Bitmask with the new hooked operations
    /// @dev All operations are initially disabled in a newly created vault. The vault creator must set their
    /// own configuration to make the vault usable
    function setHookConfig(address newHookTarget, uint32 newHookedOps) external;

    /// @notice Set new bitmap indicating which config flags should be enabled. Flags are defined in Constants.sol
    /// @param newConfigFlags Bitmask with the new config flags
    function setConfigFlags(uint32 newConfigFlags) external;

    /// @notice Set new supply and borrow caps in AmountCap format
    /// @param supplyCap The new supply cap in AmountCap fromat
    /// @param borrowCap The new borrow cap in AmountCap fromat
    function setCaps(uint16 supplyCap, uint16 borrowCap) external;

    /// @notice Set a new interest fee
    /// @param newFee The new interest fee
    function setInterestFee(uint16 newFee) external;
}

/// @title IEVault
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Interface of the EVault, an EVC enabled lending vault
interface IEVault is
    IInitialize,
    IToken,
    IVault,
    IBorrowing,
    ILiquidation,
    IRiskManager,
    IBalanceForwarder,
    IGovernance
{
    /// @notice Fetch address of the `Initialize` module
    function MODULE_INITIALIZE() external view returns (address);
    /// @notice Fetch address of the `Token` module
    function MODULE_TOKEN() external view returns (address);
    /// @notice Fetch address of the `Vault` module
    function MODULE_VAULT() external view returns (address);
    /// @notice Fetch address of the `Borrowing` module
    function MODULE_BORROWING() external view returns (address);
    /// @notice Fetch address of the `Liquidation` module
    function MODULE_LIQUIDATION() external view returns (address);
    /// @notice Fetch address of the `RiskManager` module
    function MODULE_RISKMANAGER() external view returns (address);
    /// @notice Fetch address of the `BalanceForwarder` module
    function MODULE_BALANCE_FORWARDER() external view returns (address);
    /// @notice Fetch address of the `Governance` module
    function MODULE_GOVERNANCE() external view returns (address);
}

File 4 of 11 : Constants.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

// Implementation internals

// asset amounts are shifted left by this number of bits for increased precision of debt tracking.
uint256 constant INTERNAL_DEBT_PRECISION_SHIFT = 31;
// max amount for Assets and Shares custom types based on a uint112.
uint256 constant MAX_SANE_AMOUNT = type(uint112).max;
// max debt amount fits in uint144 (112 + 31 bits).
// Last 31 bits are zeros to ensure max debt rounded up equals max sane amount.
uint256 constant MAX_SANE_DEBT_AMOUNT = uint256(MAX_SANE_AMOUNT) << INTERNAL_DEBT_PRECISION_SHIFT;
// proxy trailing calldata length in bytes.
// Three addresses, 20 bytes each: vault underlying asset, oracle and unit of account + 4 empty bytes.
uint256 constant PROXY_METADATA_LENGTH = 64;
// gregorian calendar
uint256 constant SECONDS_PER_YEAR = 365.2425 * 86400;
// max interest rate accepted from IRM. 1,000,000% APY: floor(((1000000 / 100 + 1)**(1/(86400*365.2425)) - 1) * 1e27)
uint256 constant MAX_ALLOWED_INTEREST_RATE = 291867278914945094175;
// max valid value of the ConfigAmount custom type, signifying 100%
uint16 constant CONFIG_SCALE = 1e4;

// Account status checks special values

// no account status checks should be scheduled
address constant CHECKACCOUNT_NONE = address(0);
// account status check should be scheduled for the authenticated account
address constant CHECKACCOUNT_CALLER = address(1);

// Operations

uint32 constant OP_DEPOSIT = 1 << 0;
uint32 constant OP_MINT = 1 << 1;
uint32 constant OP_WITHDRAW = 1 << 2;
uint32 constant OP_REDEEM = 1 << 3;
uint32 constant OP_TRANSFER = 1 << 4;
uint32 constant OP_SKIM = 1 << 5;
uint32 constant OP_BORROW = 1 << 6;
uint32 constant OP_REPAY = 1 << 7;
uint32 constant OP_REPAY_WITH_SHARES = 1 << 8;
uint32 constant OP_PULL_DEBT = 1 << 9;
uint32 constant OP_CONVERT_FEES = 1 << 10;
uint32 constant OP_LIQUIDATE = 1 << 11;
uint32 constant OP_FLASHLOAN = 1 << 12;
uint32 constant OP_TOUCH = 1 << 13;
uint32 constant OP_VAULT_STATUS_CHECK = 1 << 14;
// Delimiter of possible operations
uint32 constant OP_MAX_VALUE = 1 << 15;

// Config Flags

// When flag is set, debt socialization during liquidation is disabled
uint32 constant CFG_DONT_SOCIALIZE_DEBT = 1 << 0;
// When flag is set, asset is considered to be compatible with EVC sub-accounts and protections
// against sending assets to sub-accounts are disabled
uint32 constant CFG_EVC_COMPATIBLE_ASSET = 1 << 1;
// Delimiter of possible config flags
uint32 constant CFG_MAX_VALUE = 1 << 2;

// EVC authentication

// in order to perform these operations, the account doesn't need to have the vault installed as a controller
uint32 constant CONTROLLER_NEUTRAL_OPS = OP_DEPOSIT | OP_MINT | OP_WITHDRAW | OP_REDEEM | OP_TRANSFER | OP_SKIM
    | OP_REPAY | OP_REPAY_WITH_SHARES | OP_CONVERT_FEES | OP_FLASHLOAN | OP_TOUCH | OP_VAULT_STATUS_CHECK;

File 5 of 11 : BasePerspective.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.24;

import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol";
import {GenericFactory} from "evk/GenericFactory/GenericFactory.sol";

import {IPerspective} from "./interfaces/IPerspective.sol";
import {PerspectiveErrors} from "./PerspectiveErrors.sol";

/// @title BasePerspective
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A base contract for implementing a perspective.
abstract contract BasePerspective is IPerspective, PerspectiveErrors {
    using EnumerableSet for EnumerableSet.AddressSet;

    struct Transient {
        uint256 placeholder;
    }

    GenericFactory public immutable vaultFactory;

    EnumerableSet.AddressSet internal verified;
    Transient private transientVerified;
    Transient private transientErrors;
    Transient private transientVault;
    Transient private transientFailEarly;

    /// @notice Creates a new BasePerspective instance.
    /// @param vaultFactory_ The address of the GenericFactory contract.
    constructor(address vaultFactory_) {
        vaultFactory = GenericFactory(vaultFactory_);
    }

    /// @inheritdoc IPerspective
    function name() public view virtual returns (string memory);

    /// @inheritdoc IPerspective
    function perspectiveVerify(address vault, bool failEarly) public virtual {
        bytes32 transientVerifiedHash;
        assembly {
            mstore(0, vault)
            mstore(32, transientVerified.slot)
            transientVerifiedHash := keccak256(0, 64)

            // if optimistically verified, return
            if eq(tload(transientVerifiedHash), true) { return(0, 0) }
        }

        // if already verified, return
        if (verified.contains(vault)) return;

        address _vault;
        bool _failEarly;
        assembly {
            _vault := tload(transientVault.slot)
            _failEarly := tload(transientFailEarly.slot)
            tstore(transientVault.slot, vault)
            tstore(transientFailEarly.slot, failEarly)

            // optimistically assume that the vault is verified
            tstore(transientVerifiedHash, true)
        }

        // perform the perspective verification
        perspectiveVerifyInternal(vault);

        uint256 errors;
        assembly {
            // restore the cached values
            tstore(transientVault.slot, _vault)
            tstore(transientFailEarly.slot, _failEarly)

            errors := tload(transientErrors.slot)
        }

        // if early fail was not requested, we need to check for any property errors that may have occurred.
        // otherwise, we would have already reverted if there were any property errors
        if (errors != 0) revert PerspectiveError(address(this), vault, errors);

        // set the vault as permanently verified
        verified.add(vault);
        emit PerspectiveVerified(vault);
    }

    /// @inheritdoc IPerspective
    function isVerified(address vault) public view virtual returns (bool) {
        return verified.contains(vault);
    }

    /// @inheritdoc IPerspective
    function verifiedLength() public view virtual returns (uint256) {
        return verified.length();
    }

    /// @inheritdoc IPerspective
    function verifiedArray() public view virtual returns (address[] memory) {
        return verified.values();
    }

    /// @notice Internal function to perform verification of a vault.
    /// @dev This function must be defined in derived contracts to implement specific verification logic.
    /// @dev This function should use the testProperty function to test the properties of the vault.
    /// @param vault The address of the vault to verify.
    function perspectiveVerifyInternal(address vault) internal virtual;

    /// @notice Tests a property condition and handles error based on the result.
    /// @param condition The boolean condition to test, typically a property of a vault. i.e governor == address(0)
    /// @param errorCode The error code to use if the condition fails.
    function testProperty(bool condition, uint256 errorCode) internal virtual {
        if (condition) return;
        if (errorCode == 0) revert PerspectivePanic();

        bool failEarly;
        assembly {
            failEarly := tload(transientFailEarly.slot)
        }

        if (failEarly) {
            address vault;
            assembly {
                vault := tload(transientVault.slot)
            }
            revert PerspectiveError(address(this), vault, errorCode);
        } else {
            assembly {
                let errors := tload(transientErrors.slot)
                tstore(transientErrors.slot, or(errors, errorCode))
            }
        }
    }
}

File 6 of 11 : BeaconProxy.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

/// @title BeaconProxy
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A proxy contract, forwarding all calls to an implementation contract, fetched from a beacon
/// @dev The proxy attaches up to 128 bytes of metadata to the delegated call data.
contract BeaconProxy {
    // ERC-1967 beacon address slot. bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)
    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
    // Beacon implementation() selector
    bytes32 internal constant IMPLEMENTATION_SELECTOR =
        0x5c60da1b00000000000000000000000000000000000000000000000000000000;
    // Max trailing data length, 4 immutable slots
    uint256 internal constant MAX_TRAILING_DATA_LENGTH = 128;

    address internal immutable beacon;
    uint256 internal immutable metadataLength;
    bytes32 internal immutable metadata0;
    bytes32 internal immutable metadata1;
    bytes32 internal immutable metadata2;
    bytes32 internal immutable metadata3;

    event Genesis();

    constructor(bytes memory trailingData) {
        emit Genesis();

        require(trailingData.length <= MAX_TRAILING_DATA_LENGTH, "trailing data too long");

        // Beacon is always the proxy creator; store it in immutable
        beacon = msg.sender;

        // Store the beacon address in ERC-1967 slot for compatibility with block explorers
        assembly {
            sstore(BEACON_SLOT, caller())
        }

        // Record length as immutable
        metadataLength = trailingData.length;

        // Pad length with uninitialized memory so the decode will succeed
        assembly {
            mstore(trailingData, MAX_TRAILING_DATA_LENGTH)
        }
        (metadata0, metadata1, metadata2, metadata3) = abi.decode(trailingData, (bytes32, bytes32, bytes32, bytes32));
    }

    fallback() external payable {
        address beacon_ = beacon;
        uint256 metadataLength_ = metadataLength;
        bytes32 metadata0_ = metadata0;
        bytes32 metadata1_ = metadata1;
        bytes32 metadata2_ = metadata2;
        bytes32 metadata3_ = metadata3;

        assembly {
            // Fetch implementation address from the beacon
            mstore(0, IMPLEMENTATION_SELECTOR)
            // Implementation call is trusted not to revert and to return an address
            let result := staticcall(gas(), beacon_, 0, 4, 0, 32)
            let implementation := mload(0)

            // delegatecall to the implementation with trailing metadata
            calldatacopy(0, 0, calldatasize())
            mstore(calldatasize(), metadata0_)
            mstore(add(32, calldatasize()), metadata1_)
            mstore(add(64, calldatasize()), metadata2_)
            mstore(add(96, calldatasize()), metadata3_)
            result := delegatecall(gas(), implementation, 0, add(metadataLength_, calldatasize()), 0, 0)
            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }
}

File 7 of 11 : MetaProxyDeployer.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

/// @title MetaProxyDeployer
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Contract for deploying minimal proxies with metadata, based on EIP-3448.
/// @dev The metadata of the proxies does not include the data length as defined by EIP-3448, saving gas at a cost of
/// supporting variable size data.
contract MetaProxyDeployer {
    error E_DeploymentFailed();

    // Meta proxy bytecode from EIP-3488 https://eips.ethereum.org/EIPS/eip-3448
    bytes constant BYTECODE_HEAD = hex"600b380380600b3d393df3363d3d373d3d3d3d60368038038091363936013d73";
    bytes constant BYTECODE_TAIL = hex"5af43d3d93803e603457fd5bf3";

    /// @dev Creates a proxy for `targetContract` with metadata from `metadata`.
    /// @return addr A non-zero address if successful.
    function deployMetaProxy(address targetContract, bytes memory metadata) internal returns (address addr) {
        bytes memory code = abi.encodePacked(BYTECODE_HEAD, targetContract, BYTECODE_TAIL, metadata);

        assembly ("memory-safe") {
            addr := create(0, add(code, 32), mload(code))
        }

        if (addr == address(0)) revert E_DeploymentFailed();
    }
}

File 8 of 11 : IVault.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.8.0;

/// @title IVault
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice This interface defines the methods for the Vault for the purpose of integration with the Ethereum Vault
/// Connector.
interface IVault {
    /// @notice Disables a controller (this vault) for the authenticated account.
    /// @dev A controller is a vault that has been chosen for an account to have special control over account’s
    /// balances in the enabled collaterals vaults. User calls this function in order for the vault to disable itself
    /// for the account if the conditions are met (i.e. user has repaid debt in full). If the conditions are not met,
    /// the function reverts.
    function disableController() external;

    /// @notice Checks the status of an account.
    /// @dev This function must only deliberately revert if the account status is invalid. If this function reverts due
    /// to any other reason, it may render the account unusable with possibly no way to recover funds.
    /// @param account The address of the account to be checked.
    /// @param collaterals The array of enabled collateral addresses to be considered for the account status check.
    /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when
    /// account status is valid, or revert otherwise.
    function checkAccountStatus(
        address account,
        address[] calldata collaterals
    ) external view returns (bytes4 magicValue);

    /// @notice Checks the status of the vault.
    /// @dev This function must only deliberately revert if the vault status is invalid. If this function reverts due to
    /// any other reason, it may render some accounts unusable with possibly no way to recover funds.
    /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when
    /// account status is valid, or revert otherwise.
    function checkVaultStatus() external returns (bytes4 magicValue);
}

File 9 of 11 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }
}

File 10 of 11 : IPerspective.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.8.0;

/// @title IPerspective
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A contract that verifies the properties of a vault.
interface IPerspective {
    /// @notice Emitted when a vault is verified successfully.
    /// @param vault The address of the vault that has been verified.
    event PerspectiveVerified(address indexed vault);

    /// @notice Error thrown when a perspective verification fails.
    /// @param perspective The address of the perspective contract where the error occurred.
    /// @param vault The address of the vault being verified.
    /// @param codes The error codes indicating the reasons for verification failure.
    error PerspectiveError(address perspective, address vault, uint256 codes);

    /// @notice Error thrown when a panic occurs in the perspective contract.
    error PerspectivePanic();

    /// @notice Returns the name of the perspective.
    /// @dev Name should be unique and descriptive.
    /// @return The name of the perspective.
    function name() external view returns (string memory);

    /// @notice Verifies the properties of a vault.
    /// @param vault The address of the vault to verify.
    /// @param failEarly Determines whether to fail early on the first error encountered or allow the verification to
    /// continue and report all errors.
    function perspectiveVerify(address vault, bool failEarly) external;

    /// @notice Checks if a vault is verified.
    /// @param vault The address of the vault to check.
    /// @return True if the vault is verified, false otherwise.
    function isVerified(address vault) external view returns (bool);

    /// @notice Returns the number of verified vaults.
    /// @return The number of verified vaults.
    function verifiedLength() external view returns (uint256);

    /// @notice Returns an array of all verified vault addresses.
    /// @return An array of addresses of verified vaults.
    function verifiedArray() external view returns (address[] memory);
}

File 11 of 11 : PerspectiveErrors.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

/// @title PerspectiveErrors
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A contract that defines the error codes for the perspectives.
abstract contract PerspectiveErrors {
    uint256 internal constant ERROR__FACTORY = 1 << 0;
    uint256 internal constant ERROR__IMPLEMENTATION = 1 << 1;
    uint256 internal constant ERROR__UPGRADABILITY = 1 << 2;
    uint256 internal constant ERROR__SINGLETON = 1 << 3;
    uint256 internal constant ERROR__NESTING = 1 << 4;
    uint256 internal constant ERROR__ORACLE_INVALID_ROUTER = 1 << 5;
    uint256 internal constant ERROR__ORACLE_GOVERNED_ROUTER = 1 << 6;
    uint256 internal constant ERROR__ORACLE_INVALID_FALLBACK = 1 << 7;
    uint256 internal constant ERROR__ORACLE_INVALID_ROUTER_CONFIG = 1 << 8;
    uint256 internal constant ERROR__ORACLE_INVALID_ADAPTER = 1 << 9;
    uint256 internal constant ERROR__UNIT_OF_ACCOUNT = 1 << 10;
    uint256 internal constant ERROR__CREATOR = 1 << 11;
    uint256 internal constant ERROR__GOVERNOR = 1 << 12;
    uint256 internal constant ERROR__FEE_RECEIVER = 1 << 13;
    uint256 internal constant ERROR__INTEREST_FEE = 1 << 14;
    uint256 internal constant ERROR__INTEREST_RATE_MODEL = 1 << 15;
    uint256 internal constant ERROR__SUPPLY_CAP = 1 << 16;
    uint256 internal constant ERROR__BORROW_CAP = 1 << 17;
    uint256 internal constant ERROR__HOOK_TARGET = 1 << 18;
    uint256 internal constant ERROR__HOOKED_OPS = 1 << 19;
    uint256 internal constant ERROR__CONFIG_FLAGS = 1 << 20;
    uint256 internal constant ERROR__NAME = 1 << 21;
    uint256 internal constant ERROR__SYMBOL = 1 << 22;
    uint256 internal constant ERROR__LIQUIDATION_DISCOUNT = 1 << 23;
    uint256 internal constant ERROR__LIQUIDATION_COOL_OFF_TIME = 1 << 24;
    uint256 internal constant ERROR__LTV_COLLATERAL_CONFIG_LENGTH = 1 << 25;
    uint256 internal constant ERROR__LTV_COLLATERAL_CONFIG_SEPARATION = 1 << 26;
    uint256 internal constant ERROR__LTV_COLLATERAL_CONFIG_BORROW = 1 << 27;
    uint256 internal constant ERROR__LTV_COLLATERAL_CONFIG_LIQUIDATION = 1 << 28;
    uint256 internal constant ERROR__LTV_COLLATERAL_RAMPING = 1 << 29;
    uint256 internal constant ERROR__LTV_COLLATERAL_RECOGNITION = 1 << 30;
}

Settings
{
  "remappings": [
    "lib/euler-price-oracle:@openzeppelin/contracts/=lib/euler-price-oracle/lib/openzeppelin-contracts/contracts/",
    "lib/native-token-transfers/evm:openzeppelin-contracts/contracts/=lib/native-token-transfers/evm/lib/openzeppelin-contracts/contracts/",
    "lib/euler-earn:@openzeppelin/=lib/euler-earn/lib/openzeppelin-contracts/",
    "lib/euler-earn:@openzeppelin-upgradeable/=lib/euler-earn/lib/openzeppelin-contracts-upgradeable/contracts/",
    "lib/euler-earn:ethereum-vault-connector/=lib/euler-earn/lib/ethereum-vault-connector/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "ethereum-vault-connector/=lib/ethereum-vault-connector/src/",
    "evc/=lib/ethereum-vault-connector/src/",
    "evk/=lib/euler-vault-kit/src/",
    "evk-test/=lib/euler-vault-kit/test/",
    "euler-price-oracle/=lib/euler-price-oracle/src/",
    "euler-price-oracle-test/=lib/euler-price-oracle/test/",
    "fee-flow/=lib/fee-flow/src/",
    "reward-streams/=lib/reward-streams/src/",
    "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "euler-earn/=lib/euler-earn/src/",
    "native-token-transfers/=lib/native-token-transfers/evm/src/",
    "@openzeppelin-upgradeable/=lib/euler-earn/lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@pendle/core-v2/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/",
    "@pyth/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    "@redstone/evm-connector/=lib/euler-price-oracle/lib/redstone-oracles-monorepo/packages/evm-connector/contracts/",
    "@solady/=lib/euler-price-oracle/lib/solady/src/",
    "@uniswap/v3-core/=lib/euler-price-oracle/lib/v3-core/",
    "@uniswap/v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/",
    "ERC4626/=lib/euler-earn/lib/properties/lib/ERC4626/contracts/",
    "crytic-properties/=lib/euler-earn/lib/properties/contracts/",
    "ds-test/=lib/ethereum-vault-connector/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "euler-vault-kit/=lib/euler-vault-kit/",
    "forge-gas-snapshot/=lib/euler-vault-kit/lib/permit2/lib/forge-gas-snapshot/src/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "layerzero-devtools/=lib/layerzero-devtools/packages/toolbox-foundry/src/",
    "layerzero-v2/=lib/layerzero-v2/",
    "openzeppelin/=lib/ethereum-vault-connector/lib/openzeppelin-contracts/contracts/",
    "pendle-core-v2-public/=lib/euler-price-oracle/lib/pendle-core-v2-public/contracts/",
    "permit2/=lib/euler-vault-kit/lib/permit2/",
    "properties/=lib/euler-earn/lib/properties/contracts/",
    "pyth-sdk-solidity/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    "redstone-oracles-monorepo/=lib/euler-price-oracle/lib/",
    "solady/=lib/euler-price-oracle/lib/solady/src/",
    "solidity-bytes-utils/=lib/native-token-transfers/evm/lib/solidity-bytes-utils/contracts/",
    "solmate/=lib/fee-flow/lib/solmate/src/",
    "v3-core/=lib/euler-price-oracle/lib/v3-core/contracts/",
    "v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/contracts/",
    "wormhole-solidity-sdk/=lib/native-token-transfers/evm/lib/wormhole-solidity-sdk/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"vaultFactory_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"perspective","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"codes","type":"uint256"}],"name":"PerspectiveError","type":"error"},{"inputs":[],"name":"PerspectivePanic","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"PerspectiveVerified","type":"event"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"isVerified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"bool","name":"failEarly","type":"bool"}],"name":"perspectiveVerify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"singletonLookup","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultFactory","outputs":[{"internalType":"contract GenericFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifiedArray","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifiedLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a060405234801561000f575f80fd5b5060405161142e38038061142e83398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b6080516113956100995f395f8181610188015281816103820152818161043d015261058a01526113955ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c806334a7199a1161005857806334a7199a146100f15780638d5e21d31461014b578063b9209e3314610160578063d8a06f7314610183575f80fd5b806306fdde031461007e578063138721d9146100c65780632e5896e5146100dc575b5f80fd5b604080518082018252601f81527f457363726f77656420436f6c6c61746572616c20506572737065637469766500602082015290516100bd9190610ef7565b60405180910390f35b6100ce6101aa565b6040519081526020016100bd565b6100ef6100ea366004610f78565b6101b9565b005b6101266100ff366004610faf565b60066020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bd565b6101536102e3565b6040516100bd9190610fca565b61017361016e366004610faf565b6102ee565b60405190151581526020016100bd565b6101267f000000000000000000000000000000000000000000000000000000000000000081565b5f6101b45f6102ff565b905090565b5f8281526002602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815c016101f057005b6101fa5f84610308565b1561020457505050565b6004805c9060055c9085905d8360055d6001835d61022185610339565b5f8260045d8160055d5060035c8015610290576040517f818fa2cf00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff87166024820152604481018290526064015b60405180910390fd5b61029a5f87610d4b565b5060405173ffffffffffffffffffffffffffffffffffffffff8716907f570e1c1f1f2e6e95bfd6d0cae607f36c3cd5ebb7bc35c2f87299924b1bcd3920905f90a2505050505050565b60606101b45f610d6c565b5f6102f98183610308565b92915050565b5f6102f9825490565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b9392505050565b6040517f2971038800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526103f4917f000000000000000000000000000000000000000000000000000000000000000090911690632971038890602401602060405180830381865afa1580156103c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ed9190611023565b6001610d78565b6040517fa20ea5c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526104d0917f00000000000000000000000000000000000000000000000000000000000000009091169063a20ea5c1906024015f60405180830381865afa158015610483573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c891908101906110e3565b516004610d78565b5f8173ffffffffffffffffffffffffffffffffffffffff166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053e91906111e1565b6040517f2971038800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301529192506105fb917f00000000000000000000000000000000000000000000000000000000000000001690632971038890602401602060405180830381865afa1580156105cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f39190611023565b156010610d78565b6106a05f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561065e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068291906111e1565b73ffffffffffffffffffffffffffffffffffffffff16146020610d78565b6107465f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16633e8333646040518163ffffffff1660e01b8152600401602060405180830381865afa158015610703573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072791906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614610400610d78565b6107ec5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16636ce98c296040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107cd91906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614611000610d78565b6108925f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087391906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614612000610d78565b6109385f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663f3fdb15a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061091991906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614618000610d78565b5f808373ffffffffffffffffffffffffffffffffffffffff166318e22d986040518163ffffffff1660e01b81526004016040805180830381865afa158015610982573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a69190611212565b61ffff91821693501690506109ed821515806109e6575073ffffffffffffffffffffffffffffffffffffffff8481165f9081526006602052604090205416155b6008610d78565b610a0163ffffffff82161562020000610d78565b5f808573ffffffffffffffffffffffffffffffffffffffff1663cf349b7d6040518163ffffffff1660e01b81526004016040805180830381865afa158015610a4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6f9190611256565b9092509050610a9873ffffffffffffffffffffffffffffffffffffffff83161562040000610d78565b610aac63ffffffff82161562080000610d78565b50505050610b308273ffffffffffffffffffffffffffffffffffffffff16632b38a3676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b209190611280565b63ffffffff161562100000610d78565b610bae8273ffffffffffffffffffffffffffffffffffffffff16634f7e43df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba09190611299565b61ffff161562800000610d78565b610c2d8273ffffffffffffffffffffffffffffffffffffffff16634abdb9596040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1e9190611299565b61ffff16156301000000610d78565b610cc98273ffffffffffffffffffffffffffffffffffffffff16636a16ef846040518163ffffffff1660e01b81526004015f60405180830381865afa158015610c78573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610cbd91908101906112b2565b51156302000000610d78565b73ffffffffffffffffffffffffffffffffffffffff8181165f9081526006602052604090205416610d475773ffffffffffffffffffffffffffffffffffffffff8181165f90815260066020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790555b5050565b5f6103328373ffffffffffffffffffffffffffffffffffffffff8416610e30565b60605f61033283610e7c565b8115610d82575050565b805f03610dbb576040517fcb365b8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055c8015610e21576040517f818fa2cf000000000000000000000000000000000000000000000000000000008152306004808301919091525c73ffffffffffffffffffffffffffffffffffffffff811660248301526044820184905290606401610287565b60035c82811760035d50505050565b5f818152600183016020526040812054610e7557508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556102f9565b505f6102f9565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610ec957602002820191905f5260205f20905b815481526020019060010190808311610eb5575b50505050509050919050565b5f5b83811015610eef578181015183820152602001610ed7565b50505f910152565b602081525f8251806020840152610f15816040850160208701610ed5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f68575f80fd5b50565b8015158114610f68575f80fd5b5f8060408385031215610f89575f80fd5b8235610f9481610f47565b91506020830135610fa481610f6b565b809150509250929050565b5f60208284031215610fbf575f80fd5b813561033281610f47565b602080825282518282018190525f9190848201906040850190845b8181101561101757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610fe5565b50909695505050505050565b5f60208284031215611033575f80fd5b815161033281610f6b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff8111828210171561108e5761108e61103e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110db576110db61103e565b604052919050565b5f60208083850312156110f4575f80fd5b825167ffffffffffffffff8082111561110b575f80fd5b908401906060828703121561111e575f80fd5b61112661106b565b825161113181610f6b565b81528284015161114081610f47565b81850152604083015182811115611155575f80fd5b80840193505086601f840112611169575f80fd5b82518281111561117b5761117b61103e565b6111ab857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611094565b925080835287858286010111156111c0575f80fd5b6111cf81868501878701610ed5565b50604081019190915295945050505050565b5f602082840312156111f1575f80fd5b815161033281610f47565b805161ffff8116811461120d575f80fd5b919050565b5f8060408385031215611223575f80fd5b61122c836111fc565b915061123a602084016111fc565b90509250929050565b805163ffffffff8116811461120d575f80fd5b5f8060408385031215611267575f80fd5b825161127281610f47565b915061123a60208401611243565b5f60208284031215611290575f80fd5b61033282611243565b5f602082840312156112a9575f80fd5b610332826111fc565b5f60208083850312156112c3575f80fd5b825167ffffffffffffffff808211156112da575f80fd5b818501915085601f8301126112ed575f80fd5b8151818111156112ff576112ff61103e565b8060051b9150611310848301611094565b8181529183018401918481019088841115611329575f80fd5b938501935b83851015611353578451925061134383610f47565b828252938501939085019061132e565b9897505050505050505056fea264697066735822122092b19664e9bc47207742e8c9aa4b029a83ecd39f8acb338d4156ca1a50c4fddb64736f6c63430008180033000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c806334a7199a1161005857806334a7199a146100f15780638d5e21d31461014b578063b9209e3314610160578063d8a06f7314610183575f80fd5b806306fdde031461007e578063138721d9146100c65780632e5896e5146100dc575b5f80fd5b604080518082018252601f81527f457363726f77656420436f6c6c61746572616c20506572737065637469766500602082015290516100bd9190610ef7565b60405180910390f35b6100ce6101aa565b6040519081526020016100bd565b6100ef6100ea366004610f78565b6101b9565b005b6101266100ff366004610faf565b60066020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bd565b6101536102e3565b6040516100bd9190610fca565b61017361016e366004610faf565b6102ee565b60405190151581526020016100bd565b6101267f000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb81565b5f6101b45f6102ff565b905090565b5f8281526002602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815c016101f057005b6101fa5f84610308565b1561020457505050565b6004805c9060055c9085905d8360055d6001835d61022185610339565b5f8260045d8160055d5060035c8015610290576040517f818fa2cf00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff87166024820152604481018290526064015b60405180910390fd5b61029a5f87610d4b565b5060405173ffffffffffffffffffffffffffffffffffffffff8716907f570e1c1f1f2e6e95bfd6d0cae607f36c3cd5ebb7bc35c2f87299924b1bcd3920905f90a2505050505050565b60606101b45f610d6c565b5f6102f98183610308565b92915050565b5f6102f9825490565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b9392505050565b6040517f2971038800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526103f4917f000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb90911690632971038890602401602060405180830381865afa1580156103c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ed9190611023565b6001610d78565b6040517fa20ea5c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526104d0917f000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb9091169063a20ea5c1906024015f60405180830381865afa158015610483573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c891908101906110e3565b516004610d78565b5f8173ffffffffffffffffffffffffffffffffffffffff166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053e91906111e1565b6040517f2971038800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301529192506105fb917f000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb1690632971038890602401602060405180830381865afa1580156105cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f39190611023565b156010610d78565b6106a05f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561065e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068291906111e1565b73ffffffffffffffffffffffffffffffffffffffff16146020610d78565b6107465f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16633e8333646040518163ffffffff1660e01b8152600401602060405180830381865afa158015610703573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072791906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614610400610d78565b6107ec5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16636ce98c296040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107cd91906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614611000610d78565b6108925f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663b3f006746040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087391906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614612000610d78565b6109385f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663f3fdb15a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061091991906111e1565b73ffffffffffffffffffffffffffffffffffffffff1614618000610d78565b5f808373ffffffffffffffffffffffffffffffffffffffff166318e22d986040518163ffffffff1660e01b81526004016040805180830381865afa158015610982573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a69190611212565b61ffff91821693501690506109ed821515806109e6575073ffffffffffffffffffffffffffffffffffffffff8481165f9081526006602052604090205416155b6008610d78565b610a0163ffffffff82161562020000610d78565b5f808573ffffffffffffffffffffffffffffffffffffffff1663cf349b7d6040518163ffffffff1660e01b81526004016040805180830381865afa158015610a4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6f9190611256565b9092509050610a9873ffffffffffffffffffffffffffffffffffffffff83161562040000610d78565b610aac63ffffffff82161562080000610d78565b50505050610b308273ffffffffffffffffffffffffffffffffffffffff16632b38a3676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b209190611280565b63ffffffff161562100000610d78565b610bae8273ffffffffffffffffffffffffffffffffffffffff16634f7e43df6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba09190611299565b61ffff161562800000610d78565b610c2d8273ffffffffffffffffffffffffffffffffffffffff16634abdb9596040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c1e9190611299565b61ffff16156301000000610d78565b610cc98273ffffffffffffffffffffffffffffffffffffffff16636a16ef846040518163ffffffff1660e01b81526004015f60405180830381865afa158015610c78573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610cbd91908101906112b2565b51156302000000610d78565b73ffffffffffffffffffffffffffffffffffffffff8181165f9081526006602052604090205416610d475773ffffffffffffffffffffffffffffffffffffffff8181165f90815260066020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790555b5050565b5f6103328373ffffffffffffffffffffffffffffffffffffffff8416610e30565b60605f61033283610e7c565b8115610d82575050565b805f03610dbb576040517fcb365b8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055c8015610e21576040517f818fa2cf000000000000000000000000000000000000000000000000000000008152306004808301919091525c73ffffffffffffffffffffffffffffffffffffffff811660248301526044820184905290606401610287565b60035c82811760035d50505050565b5f818152600183016020526040812054610e7557508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556102f9565b505f6102f9565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610ec957602002820191905f5260205f20905b815481526020019060010190808311610eb5575b50505050509050919050565b5f5b83811015610eef578181015183820152602001610ed7565b50505f910152565b602081525f8251806020840152610f15816040850160208701610ed5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f68575f80fd5b50565b8015158114610f68575f80fd5b5f8060408385031215610f89575f80fd5b8235610f9481610f47565b91506020830135610fa481610f6b565b809150509250929050565b5f60208284031215610fbf575f80fd5b813561033281610f47565b602080825282518282018190525f9190848201906040850190845b8181101561101757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610fe5565b50909695505050505050565b5f60208284031215611033575f80fd5b815161033281610f6b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff8111828210171561108e5761108e61103e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110db576110db61103e565b604052919050565b5f60208083850312156110f4575f80fd5b825167ffffffffffffffff8082111561110b575f80fd5b908401906060828703121561111e575f80fd5b61112661106b565b825161113181610f6b565b81528284015161114081610f47565b81850152604083015182811115611155575f80fd5b80840193505086601f840112611169575f80fd5b82518281111561117b5761117b61103e565b6111ab857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611094565b925080835287858286010111156111c0575f80fd5b6111cf81868501878701610ed5565b50604081019190915295945050505050565b5f602082840312156111f1575f80fd5b815161033281610f47565b805161ffff8116811461120d575f80fd5b919050565b5f8060408385031215611223575f80fd5b61122c836111fc565b915061123a602084016111fc565b90509250929050565b805163ffffffff8116811461120d575f80fd5b5f8060408385031215611267575f80fd5b825161127281610f47565b915061123a60208401611243565b5f60208284031215611290575f80fd5b61033282611243565b5f602082840312156112a9575f80fd5b610332826111fc565b5f60208083850312156112c3575f80fd5b825167ffffffffffffffff808211156112da575f80fd5b818501915085601f8301126112ed575f80fd5b8151818111156112ff576112ff61103e565b8060051b9150611310848301611094565b8181529183018401918481019088841115611329575f80fd5b938501935b83851015611353578451925061134383610f47565b828252938501939085019061132e565b9897505050505050505056fea264697066735822122092b19664e9bc47207742e8c9aa4b029a83ecd39f8acb338d4156ca1a50c4fddb64736f6c63430008180033

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

000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb

-----Decoded View---------------
Arg [0] : vaultFactory_ (address): 0xF075cC8660B51D0b8a4474e3f47eDAC5fA034cFB

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f075cc8660b51d0b8a4474e3f47edac5fa034cfb


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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.