Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
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
Contract Source Code (Solidity Standard Json-Input format)
// 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; } } }
// 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]; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import {IVault as IEVCVault} from "ethereum-vault-connector/interfaces/IVault.sol"; // Full interface of EVault and all it's modules /// @title IInitialize /// @notice Interface of the initialization module of EVault interface IInitialize { /// @notice Initialization of the newly deployed proxy contract /// @param proxyCreator Account which created the proxy or should be the initial governor function initialize(address proxyCreator) external; } /// @title IERC20 /// @notice Interface of the EVault's Initialize module interface IERC20 { /// @notice Vault share token (eToken) name, ie "Euler Vault: DAI" /// @return The name of the eToken function name() external view returns (string memory); /// @notice Vault share token (eToken) symbol, ie "eDAI" /// @return The symbol of the eToken function symbol() external view returns (string memory); /// @notice Decimals, the same as the asset's or 18 if the asset doesn't implement `decimals()` /// @return The decimals of the eToken function decimals() external view returns (uint8); /// @notice Sum of all eToken balances /// @return The total supply of the eToken function totalSupply() external view returns (uint256); /// @notice Balance of a particular account, in eTokens /// @param account Address to query /// @return The balance of the account function balanceOf(address account) external view returns (uint256); /// @notice Retrieve the current allowance /// @param holder The account holding the eTokens /// @param spender Trusted address /// @return The allowance from holder for spender function allowance(address holder, address spender) external view returns (uint256); /// @notice Transfer eTokens to another address /// @param to Recipient account /// @param amount In shares. /// @return True if transfer succeeded function transfer(address to, uint256 amount) external returns (bool); /// @notice Transfer eTokens from one address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @param amount In shares /// @return True if transfer succeeded function transferFrom(address from, address to, uint256 amount) external returns (bool); /// @notice Allow spender to access an amount of your eTokens /// @param spender Trusted address /// @param amount Use max uint for "infinite" allowance /// @return True if approval succeeded function approve(address spender, uint256 amount) external returns (bool); } /// @title IToken /// @notice Interface of the EVault's Token module interface IToken is IERC20 { /// @notice Transfer the full eToken balance of an address to another /// @param from This address must've approved the to address /// @param to Recipient account /// @return True if transfer succeeded function transferFromMax(address from, address to) external returns (bool); } /// @title IERC4626 /// @notice Interface of an ERC4626 vault interface IERC4626 { /// @notice Vault's underlying asset /// @return The vault's underlying asset function asset() external view returns (address); /// @notice Total amount of managed assets, cash and borrows /// @return The total amount of assets function totalAssets() external view returns (uint256); /// @notice Calculate amount of assets corresponding to the requested shares amount /// @param shares Amount of shares to convert /// @return The amount of assets function convertToAssets(uint256 shares) external view returns (uint256); /// @notice Calculate amount of shares corresponding to the requested assets amount /// @param assets Amount of assets to convert /// @return The amount of shares function convertToShares(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user can deposit /// @param account Address to query /// @return The max amount of assets the account can deposit function maxDeposit(address account) external view returns (uint256); /// @notice Calculate an amount of shares that would be created by depositing assets /// @param assets Amount of assets deposited /// @return Amount of shares received function previewDeposit(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user can mint /// @param account Address to query /// @return The max amount of shares the account can mint function maxMint(address account) external view returns (uint256); /// @notice Calculate an amount of assets that would be required to mint requested amount of shares /// @param shares Amount of shares to be minted /// @return Required amount of assets function previewMint(uint256 shares) external view returns (uint256); /// @notice Fetch the maximum amount of assets a user is allowed to withdraw /// @param owner Account holding the shares /// @return The maximum amount of assets the owner is allowed to withdraw function maxWithdraw(address owner) external view returns (uint256); /// @notice Calculate the amount of shares that will be burned when withdrawing requested amount of assets /// @param assets Amount of assets withdrawn /// @return Amount of shares burned function previewWithdraw(uint256 assets) external view returns (uint256); /// @notice Fetch the maximum amount of shares a user is allowed to redeem for assets /// @param owner Account holding the shares /// @return The maximum amount of shares the owner is allowed to redeem function maxRedeem(address owner) external view returns (uint256); /// @notice Calculate the amount of assets that will be transferred when redeeming requested amount of shares /// @param shares Amount of shares redeemed /// @return Amount of assets transferred function previewRedeem(uint256 shares) external view returns (uint256); /// @notice Transfer requested amount of underlying tokens from sender to the vault pool in return for shares /// @param amount Amount of assets to deposit (use max uint256 for full underlying token balance) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Deposit will round down the amount of assets that are converted to shares. To prevent losses consider using /// mint instead. function deposit(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from sender to the vault pool in return for requested amount of shares /// @param amount Amount of shares to be minted /// @param receiver An account to receive the shares /// @return Amount of assets deposited function mint(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer requested amount of underlying tokens from the vault and decrease account's shares balance /// @param amount Amount of assets to withdraw /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn /// @return Amount of shares burned function withdraw(uint256 amount, address receiver, address owner) external returns (uint256); /// @notice Burn requested shares and transfer corresponding underlying tokens from the vault to the receiver /// @param amount Amount of shares to burn (use max uint256 to burn full owner balance) /// @param receiver Account to receive the withdrawn assets /// @param owner Account holding the shares to burn. /// @return Amount of assets transferred function redeem(uint256 amount, address receiver, address owner) external returns (uint256); } /// @title IVault /// @notice Interface of the EVault's Vault module interface IVault is IERC4626 { /// @notice Balance of the fees accumulator, in shares /// @return The accumulated fees in shares function accumulatedFees() external view returns (uint256); /// @notice Balance of the fees accumulator, in underlying units /// @return The accumulated fees in asset units function accumulatedFeesAssets() external view returns (uint256); /// @notice Address of the original vault creator /// @return The address of the creator function creator() external view returns (address); /// @notice Creates shares for the receiver, from excess asset balances of the vault (not accounted for in `cash`) /// @param amount Amount of assets to claim (use max uint256 to claim all available assets) /// @param receiver An account to receive the shares /// @return Amount of shares minted /// @dev Could be used as an alternative deposit flow in certain scenarios. E.g. swap directly to the vault, call /// `skim` to claim deposit. function skim(uint256 amount, address receiver) external returns (uint256); } /// @title IBorrowing /// @notice Interface of the EVault's Borrowing module interface IBorrowing { /// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued) /// @return The total borrows in asset units function totalBorrows() external view returns (uint256); /// @notice Sum of all outstanding debts, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @return The total borrows in internal debt precision function totalBorrowsExact() external view returns (uint256); /// @notice Balance of vault assets as tracked by deposits/withdrawals and borrows/repays /// @return The amount of assets the vault tracks as current direct holdings function cash() external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units /// @param account Address to query /// @return The debt of the account in asset units function debtOf(address account) external view returns (uint256); /// @notice Debt owed by a particular account, in underlying units scaled up by shifting /// INTERNAL_DEBT_PRECISION_SHIFT bits /// @param account Address to query /// @return The debt of the account in internal precision function debtOfExact(address account) external view returns (uint256); /// @notice Retrieves the current interest rate for an asset /// @return The interest rate in yield-per-second, scaled by 10**27 function interestRate() external view returns (uint256); /// @notice Retrieves the current interest rate accumulator for an asset /// @return An opaque accumulator that increases as interest is accrued function interestAccumulator() external view returns (uint256); /// @notice Returns an address of the sidecar DToken /// @return The address of the DToken function dToken() external view returns (address); /// @notice Transfer underlying tokens from the vault to the sender, and increase sender's debt /// @param amount Amount of assets to borrow (use max uint256 for all available tokens) /// @param receiver Account receiving the borrowed tokens /// @return Amount of assets borrowed function borrow(uint256 amount, address receiver) external returns (uint256); /// @notice Transfer underlying tokens from the sender to the vault, and decrease receiver's debt /// @param amount Amount of debt to repay in assets (use max uint256 for full debt) /// @param receiver Account holding the debt to be repaid /// @return Amount of assets repaid function repay(uint256 amount, address receiver) external returns (uint256); /// @notice Pay off liability with shares ("self-repay") /// @param amount In asset units (use max uint256 to repay the debt in full or up to the available deposit) /// @param receiver Account to remove debt from by burning sender's shares /// @return shares Amount of shares burned /// @return debt Amount of debt removed in assets /// @dev Equivalent to withdrawing and repaying, but no assets are needed to be present in the vault /// @dev Contrary to a regular `repay`, if account is unhealthy, the repay amount must bring the account back to /// health, or the operation will revert during account status check function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt); /// @notice Take over debt from another account /// @param amount Amount of debt in asset units (use max uint256 for all the account's debt) /// @param from Account to pull the debt from /// @dev Due to internal debt precision accounting, the liability reported on either or both accounts after /// calling `pullDebt` may not match the `amount` requested precisely function pullDebt(uint256 amount, address from) external; /// @notice Request a flash-loan. A onFlashLoan() callback in msg.sender will be invoked, which must repay the loan /// to the main Euler address prior to returning. /// @param amount In asset units /// @param data Passed through to the onFlashLoan() callback, so contracts don't need to store transient data in /// storage function flashLoan(uint256 amount, bytes calldata data) external; /// @notice Updates interest accumulator and totalBorrows, credits reserves, re-targets interest rate, and logs /// vault status function touch() external; } /// @title ILiquidation /// @notice Interface of the EVault's Liquidation module interface ILiquidation { /// @notice Checks to see if a liquidation would be profitable, without actually doing anything /// @param liquidator Address that will initiate the liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @return maxRepay Max amount of debt that can be repaid, in asset units /// @return maxYield Yield in collateral corresponding to max allowed amount of debt to be repaid, in collateral /// balance (shares for vaults) function checkLiquidation(address liquidator, address violator, address collateral) external view returns (uint256 maxRepay, uint256 maxYield); /// @notice Attempts to perform a liquidation /// @param violator Address that may be in collateral violation /// @param collateral Collateral which is to be seized /// @param repayAssets The amount of underlying debt to be transferred from violator to sender, in asset units (use /// max uint256 to repay the maximum possible amount). Meant as slippage check together with `minYieldBalance` /// @param minYieldBalance The minimum acceptable amount of collateral to be transferred from violator to sender, in /// collateral balance units (shares for vaults). Meant as slippage check together with `repayAssets` /// @dev If `repayAssets` is set to max uint256 it is assumed the caller will perform their own slippage checks to /// make sure they are not taking on too much debt. This option is mainly meant for smart contract liquidators function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external; } /// @title IRiskManager /// @notice Interface of the EVault's RiskManager module interface IRiskManager is IEVCVault { /// @notice Retrieve account's total liquidity /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collateralValue Total risk adjusted value of all collaterals in unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidity(address account, bool liquidation) external view returns (uint256 collateralValue, uint256 liabilityValue); /// @notice Retrieve account's liquidity per collateral /// @param account Account holding debt in this vault /// @param liquidation Flag to indicate if the calculation should be performed in liquidation vs account status /// check mode, where different LTV values might apply. /// @return collaterals Array of collaterals enabled /// @return collateralValues Array of risk adjusted collateral values corresponding to items in collaterals array. /// In unit of account /// @return liabilityValue Value of debt in unit of account function accountLiquidityFull(address account, bool liquidation) external view returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue); /// @notice Release control of the account on EVC if no outstanding debt is present function disableController() external; /// @notice Checks the status of an account and reverts if account is not healthy /// @param account The address of the account to be checked /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkAccountStatus(address account, address[] calldata collaterals) external view returns (bytes4); /// @notice Checks the status of the vault and reverts if caps are exceeded /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. /// @dev Only callable by EVC during status checks function checkVaultStatus() external returns (bytes4); } /// @title IBalanceForwarder /// @notice Interface of the EVault's BalanceForwarder module interface IBalanceForwarder { /// @notice Retrieve the address of rewards contract, tracking changes in account's balances /// @return The balance tracker address function balanceTrackerAddress() external view returns (address); /// @notice Retrieves boolean indicating if the account opted in to forward balance changes to the rewards contract /// @param account Address to query /// @return True if balance forwarder is enabled function balanceForwarderEnabled(address account) external view returns (bool); /// @notice Enables balance forwarding for the authenticated account /// @dev Only the authenticated account can enable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the current account's balance function enableBalanceForwarder() external; /// @notice Disables balance forwarding for the authenticated account /// @dev Only the authenticated account can disable balance forwarding for itself /// @dev Should call the IBalanceTracker hook with the account's balance of 0 function disableBalanceForwarder() external; } /// @title IGovernance /// @notice Interface of the EVault's Governance module interface IGovernance { /// @notice Retrieves the address of the governor /// @return The governor address function governorAdmin() external view returns (address); /// @notice Retrieves address of the governance fee receiver /// @return The fee receiver address function feeReceiver() external view returns (address); /// @notice Retrieves the interest fee in effect for the vault /// @return Amount of interest that is redirected as a fee, as a fraction scaled by 1e4 function interestFee() external view returns (uint16); /// @notice Looks up an asset's currently configured interest rate model /// @return Address of the interest rate contract or address zero to indicate 0% interest function interestRateModel() external view returns (address); /// @notice Retrieves the ProtocolConfig address /// @return The protocol config address function protocolConfigAddress() external view returns (address); /// @notice Retrieves the protocol fee share /// @return A percentage share of fees accrued belonging to the protocol, in 1e4 scale function protocolFeeShare() external view returns (uint256); /// @notice Retrieves the address which will receive protocol's fees /// @notice The protocol fee receiver address function protocolFeeReceiver() external view returns (address); /// @notice Retrieves supply and borrow caps in AmountCap format /// @return supplyCap The supply cap in AmountCap format /// @return borrowCap The borrow cap in AmountCap format function caps() external view returns (uint16 supplyCap, uint16 borrowCap); /// @notice Retrieves the borrow LTV of the collateral, which is used to determine if the account is healthy during /// account status checks. /// @param collateral The address of the collateral to query /// @return Borrowing LTV in 1e4 scale function LTVBorrow(address collateral) external view returns (uint16); /// @notice Retrieves the current liquidation LTV, which is used to determine if the account is eligible for /// liquidation /// @param collateral The address of the collateral to query /// @return Liquidation LTV in 1e4 scale function LTVLiquidation(address collateral) external view returns (uint16); /// @notice Retrieves LTV configuration for the collateral /// @param collateral Collateral asset /// @return borrowLTV The current value of borrow LTV for originating positions /// @return liquidationLTV The value of fully converged liquidation LTV /// @return initialLiquidationLTV The initial value of the liquidation LTV, when the ramp began /// @return targetTimestamp The timestamp when the liquidation LTV is considered fully converged /// @return rampDuration The time it takes for the liquidation LTV to converge from the initial value to the fully /// converged value function LTVFull(address collateral) external view returns ( uint16 borrowLTV, uint16 liquidationLTV, uint16 initialLiquidationLTV, uint48 targetTimestamp, uint32 rampDuration ); /// @notice Retrieves a list of collaterals with configured LTVs /// @return List of asset collaterals /// @dev Returned assets could have the ltv disabled (set to zero) function LTVList() external view returns (address[] memory); /// @notice Retrieves the maximum liquidation discount /// @return The maximum liquidation discount in 1e4 scale /// @dev The default value, which is zero, is deliberately bad, as it means there would be no incentive to liquidate /// unhealthy users. The vault creator must take care to properly select the limit, given the underlying and /// collaterals used. function maxLiquidationDiscount() external view returns (uint16); /// @notice Retrieves liquidation cool-off time, which must elapse after successful account status check before /// account can be liquidated /// @return The liquidation cool off time in seconds function liquidationCoolOffTime() external view returns (uint16); /// @notice Retrieves a hook target and a bitmask indicating which operations call the hook target /// @return hookTarget Address of the hook target contract /// @return hookedOps Bitmask with operations that should call the hooks. See Constants.sol for a list of operations function hookConfig() external view returns (address hookTarget, uint32 hookedOps); /// @notice Retrieves a bitmask indicating enabled config flags /// @return Bitmask with config flags enabled function configFlags() external view returns (uint32); /// @notice Address of EthereumVaultConnector contract /// @return The EVC address function EVC() external view returns (address); /// @notice Retrieves a reference asset used for liquidity calculations /// @return The address of the reference asset function unitOfAccount() external view returns (address); /// @notice Retrieves the address of the oracle contract /// @return The address of the oracle function oracle() external view returns (address); /// @notice Retrieves the Permit2 contract address /// @return The address of the Permit2 contract function permit2Address() external view returns (address); /// @notice Splits accrued fees balance according to protocol fee share and transfers shares to the governor fee /// receiver and protocol fee receiver function convertFees() external; /// @notice Set a new governor address /// @param newGovernorAdmin The new governor address /// @dev Set to zero address to renounce privileges and make the vault non-governed function setGovernorAdmin(address newGovernorAdmin) external; /// @notice Set a new governor fee receiver address /// @param newFeeReceiver The new fee receiver address function setFeeReceiver(address newFeeReceiver) external; /// @notice Set a new LTV config /// @param collateral Address of collateral to set LTV for /// @param borrowLTV New borrow LTV, for assessing account's health during account status checks, in 1e4 scale /// @param liquidationLTV New liquidation LTV after ramp ends in 1e4 scale /// @param rampDuration Ramp duration in seconds function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external; /// @notice Set a new maximum liquidation discount /// @param newDiscount New maximum liquidation discount in 1e4 scale /// @dev If the discount is zero (the default), the liquidators will not be incentivized to liquidate unhealthy /// accounts function setMaxLiquidationDiscount(uint16 newDiscount) external; /// @notice Set a new liquidation cool off time, which must elapse after successful account status check before /// account can be liquidated /// @param newCoolOffTime The new liquidation cool off time in seconds /// @dev Setting cool off time to zero allows liquidating the account in the same block as the last successful /// account status check function setLiquidationCoolOffTime(uint16 newCoolOffTime) external; /// @notice Set a new interest rate model contract /// @param newModel The new IRM address /// @dev If the new model reverts, perhaps due to governor error, the vault will silently use a zero interest /// rate. Governor should make sure the new interest rates are computed as expected. function setInterestRateModel(address newModel) external; /// @notice Set a new hook target and a new bitmap indicating which operations should call the hook target. /// Operations are defined in Constants.sol. /// @param newHookTarget The new hook target address. Use address(0) to simply disable hooked operations /// @param newHookedOps Bitmask with the new hooked operations /// @dev All operations are initially disabled in a newly created vault. The vault creator must set their /// own configuration to make the vault usable function setHookConfig(address newHookTarget, uint32 newHookedOps) external; /// @notice Set new bitmap indicating which config flags should be enabled. Flags are defined in Constants.sol /// @param newConfigFlags Bitmask with the new config flags function setConfigFlags(uint32 newConfigFlags) external; /// @notice Set new supply and borrow caps in AmountCap format /// @param supplyCap The new supply cap in AmountCap fromat /// @param borrowCap The new borrow cap in AmountCap fromat function setCaps(uint16 supplyCap, uint16 borrowCap) external; /// @notice Set a new interest fee /// @param newFee The new interest fee function setInterestFee(uint16 newFee) external; } /// @title IEVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Interface of the EVault, an EVC enabled lending vault interface IEVault is IInitialize, IToken, IVault, IBorrowing, ILiquidation, IRiskManager, IBalanceForwarder, IGovernance { /// @notice Fetch address of the `Initialize` module function MODULE_INITIALIZE() external view returns (address); /// @notice Fetch address of the `Token` module function MODULE_TOKEN() external view returns (address); /// @notice Fetch address of the `Vault` module function MODULE_VAULT() external view returns (address); /// @notice Fetch address of the `Borrowing` module function MODULE_BORROWING() external view returns (address); /// @notice Fetch address of the `Liquidation` module function MODULE_LIQUIDATION() external view returns (address); /// @notice Fetch address of the `RiskManager` module function MODULE_RISKMANAGER() external view returns (address); /// @notice Fetch address of the `BalanceForwarder` module function MODULE_BALANCE_FORWARDER() external view returns (address); /// @notice Fetch address of the `Governance` module function MODULE_GOVERNANCE() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; // 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;
// 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)) } } } }
// 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()) } } } }
// 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(); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IVault /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice This interface defines the methods for the Vault for the purpose of integration with the Ethereum Vault /// Connector. interface IVault { /// @notice Disables a controller (this vault) for the authenticated account. /// @dev A controller is a vault that has been chosen for an account to have special control over account’s /// balances in the enabled collaterals vaults. User calls this function in order for the vault to disable itself /// for the account if the conditions are met (i.e. user has repaid debt in full). If the conditions are not met, /// the function reverts. function disableController() external; /// @notice Checks the status of an account. /// @dev This function must only deliberately revert if the account status is invalid. If this function reverts due /// to any other reason, it may render the account unusable with possibly no way to recover funds. /// @param account The address of the account to be checked. /// @param collaterals The array of enabled collateral addresses to be considered for the account status check. /// @return magicValue Must return the bytes4 magic value 0xb168c58f (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkAccountStatus( address account, address[] calldata collaterals ) external view returns (bytes4 magicValue); /// @notice Checks the status of the vault. /// @dev This function must only deliberately revert if the vault status is invalid. If this function reverts due to /// any other reason, it may render some accounts unusable with possibly no way to recover funds. /// @return magicValue Must return the bytes4 magic value 0x4b3d1223 (which is a selector of this function) when /// account status is valid, or revert otherwise. function checkVaultStatus() external returns (bytes4 magicValue); }
// SPDX-License-Identifier: 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; } }
// 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); }
// 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; }
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.