Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EdgeFactoryPerspective
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 {IEdgeFactory} from "../../EdgeFactory/interfaces/IEdgeFactory.sol"; import {BasePerspective} from "../implementation/BasePerspective.sol"; /// @title EdgeFactoryPerspective /// @custom:security-contact [email protected] /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice A contract that verifies whether a vault was deployed by the Edge Factory. contract EdgeFactoryPerspective is BasePerspective { /// @notice Creates a new EdgeFactoryPerspective instance. /// @param edgeFactory_ The address of the EdgeFactory contract. constructor(address edgeFactory_) BasePerspective(edgeFactory_) {} /// @inheritdoc BasePerspective function name() public pure virtual override returns (string memory) { return "Edge Factory Perspective"; } /// @inheritdoc BasePerspective function perspectiveVerifyInternal(address vault) internal virtual override { testProperty(IEdgeFactory(address(vaultFactory)).isDeployed(vault), ERROR__FACTORY); } /// @inheritdoc BasePerspective function isVerified(address vault) public view virtual override returns (bool) { return IEdgeFactory(address(vaultFactory)).isDeployed(vault); } /// @inheritdoc BasePerspective function verifiedLength() public view virtual override returns (uint256) { address[][] memory list = IEdgeFactory(address(vaultFactory)).getDeploymentsListSlice(0, type(uint256).max); uint256 count; for (uint256 i = 0; i < list.length; ++i) { count += list[i].length; } return count; } /// @inheritdoc BasePerspective function verifiedArray() public view virtual override returns (address[] memory) { address[][] memory list = IEdgeFactory(address(vaultFactory)).getDeploymentsListSlice(0, type(uint256).max); uint256 count; for (uint256 i = 0; i < list.length; ++i) { count += list[i].length; } address[] memory result = new address[](count); count = 0; for (uint256 i = 0; i < list.length; ++i) { for (uint256 j = 0; j < list[i].length; ++j) { result[count++] = list[i][j]; } } return result; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title IEdgeFactory /// @custom:security-contact [email protected] /// @author Objective Labs (https://www.objectivelabs.io/) /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice Factory contract for deploying and configuring Edge markets interface IEdgeFactory { /// @notice Parameters for deploying a vault /// @param asset The underlying asset of the vault /// @param irm The address of the interest rate model, ignored if escrow /// @param escrow True if the vault is collateral only, false if it is borrowable struct VaultParams { address asset; address irm; bool escrow; } /// @notice Parameters for configuring an oracle adapter in the router /// @param base The base token address /// @param adapter The oracle adapter address struct AdapterParams { address base; address adapter; } /// @notice Parameters for configuring the oracle router /// @param externalResolvedVaults Array of external ERC4626 vaults to be resolved /// @param adapters Array of oracle adapter configurations struct RouterParams { address[] externalResolvedVaults; AdapterParams[] adapters; } /// @notice Parameters for setting loan-to-value ratios between vaults /// @param collateralVaultIndex Index of the collateral vault in the vaults array /// @param controllerVaultIndex Index of the controller vault in the vaults array /// @param borrowLTV The loan-to-value ratio for borrowing (1e4 = 100%) /// @param liquidationLTV The loan-to-value ratio for liquidation (1e4 = 100%) struct LTVParams { uint256 collateralVaultIndex; uint256 controllerVaultIndex; uint16 borrowLTV; uint16 liquidationLTV; } /// @notice Parameters for deploying an Edge market /// @param vaults Array of vault configurations /// @param router Router configuration /// @param ltv Array of LTV configurations between vaults /// @param unitOfAccount The unit of account token address struct DeployParams { VaultParams[] vaults; RouterParams router; LTVParams[] ltv; address unitOfAccount; } /// @notice Emitted when a new Edge market is deployed /// @param router The deployed router contract /// @param vaults Array of constituent vaults event EdgeDeployed(address indexed router, address[] vaults); /// @notice Thrown when attempting to deploy with fewer than 2 vaults error E_TooFewVaults(); /// @notice Thrown when attempting to query deployments with invalid indices error E_BadQuery(); /// @notice Deploys an Edge market /// @param params The deployment parameters /// @dev This function performs the following steps: /// @dev 1. Deploys a router /// @dev 2. Configures price adapters in the router /// @dev 3. Resolves external vaults in the router /// @dev 4. Deploys and configures vaults with specified parameters /// @dev 5. Sets up LTV relationships between vaults /// @dev 6. Renounces governance for all deployed contracts /// @dev After deployment, governance is permanently renounced /// @dev Reverts if: /// @dev - Less than 2 vaults are specified in params /// @return The deployed router contract /// @return An array of vault addresses in the market function deploy(DeployParams calldata params) external returns (address, address[] memory); /// @notice The factory contract for deploying vaults function eVaultFactory() external view returns (address); /// @notice The factory contract for deploying routers function eulerRouterFactory() external view returns (address); /// @notice Address of the escrowed collateral perspective contract function escrowedCollateralPerspective() external view returns (address); /// @notice Get the array of vaults for a given deployment index function getDeployment(uint256 i) external view returns (address[] memory); /// @notice Get the total number of deployments /// @return count The total number of Edge markets deployed function getDeploymentsListLength() external view returns (uint256); /// @notice Get a slice of vault deployment addresses /// @param start The start index of the slice from the list of deployed routers (inclusive) /// @param end The end index of the slice from the list of deployed routers (exclusive) /// @return list An array of arrays of vault addresses, where each inner array contains all vaults for a single Edge /// market function getDeploymentsListSlice(uint256 start, uint256 end) external view returns (address[][] memory list); /// @notice Whether a vault belongs to any one Edge market function isDeployed(address vault) external view returns (bool); }
// 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: 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; 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; /// @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; }
// 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(); } }
{ "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
Contract ABI
API[{"inputs":[{"internalType":"address","name":"edgeFactory_","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":[],"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
60a060405234801561000f575f80fd5b50604051610d5d380380610d5d83398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b608051610cbd6100a05f395f8181610123015281816101d80152818161043e01528181610654015261073f0152610cbd5ff3fe608060405234801561000f575f80fd5b506004361061006f575f3560e01c80638d5e21d31161004d5780638d5e21d3146100e6578063b9209e33146100fb578063d8a06f731461011e575f80fd5b806306fdde0314610073578063138721d9146100bb5780632e5896e5146100d1575b5f80fd5b604080518082018252601881527f4564676520466163746f72792050657273706563746976650000000000000000602082015290516100b291906108d9565b60405180910390f35b6100c361016a565b6040519081526020016100b2565b6100e46100df366004610971565b6102a6565b005b6100ee6103d0565b6040516100b291906109a8565b61010e610109366004610a01565b61060d565b60405190151581526020016100b2565b6101457f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b2565b6040517fe536913d0000000000000000000000000000000000000000000000000000000081525f600482018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602483015290819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e536913d906044015f60405180830381865afa15801561021c573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526102619190810190610abb565b90505f805b825181101561029f5782818151811061028157610281610bc8565b602002602001015151826102959190610c22565b9150600101610266565b5092915050565b5f8281526002602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815c016102dd57005b6102e75f846106c5565b156102f157505050565b6004805c9060055c9085905d8360055d6001835d61030e856106f6565b5f8260045d8160055d5060035c801561037d576040517f818fa2cf00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff87166024820152604481018290526064015b60405180910390fd5b6103875f876107b4565b5060405173ffffffffffffffffffffffffffffffffffffffff8716907f570e1c1f1f2e6e95bfd6d0cae607f36c3cd5ebb7bc35c2f87299924b1bcd3920905f90a2505050505050565b6040517fe536913d0000000000000000000000000000000000000000000000000000000081525f600482018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602483015260609173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e536913d906044015f60405180830381865afa158015610482573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c79190810190610abb565b90505f805b8251811015610505578281815181106104e7576104e7610bc8565b602002602001015151826104fb9190610c22565b91506001016104cc565b505f8167ffffffffffffffff81111561052057610520610a1c565b604051908082528060200260200182016040528015610549578160200160208202803683370190505b5090505f91505f5b8351811015610605575f5b84828151811061056e5761056e610bc8565b6020026020010151518110156105fc5784828151811061059057610590610bc8565b602002602001015181815181106105a9576105a9610bc8565b60200260200101518385806105bd90610c35565b9650815181106105cf576105cf610bc8565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161055c565b50600101610551565b509392505050565b6040517f90184b0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f0000000000000000000000000000000000000000000000000000000000000000909116906390184b0290602401602060405180830381865afa15801561069b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106bf9190610c6c565b92915050565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b9392505050565b6040517f90184b0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526107b1917f0000000000000000000000000000000000000000000000000000000000000000909116906390184b0290602401602060405180830381865afa158015610786573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107aa9190610c6c565b60016107d5565b50565b5f6106ef8373ffffffffffffffffffffffffffffffffffffffff841661088d565b81156107df575050565b805f03610818576040517fcb365b8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055c801561087e576040517f818fa2cf000000000000000000000000000000000000000000000000000000008152306004808301919091525c73ffffffffffffffffffffffffffffffffffffffff811660248301526044820184905290606401610374565b60035c82811760035d50505050565b5f8181526001830160205260408120546108d257508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106bf565b505f6106bf565b5f602080835283518060208501525f5b81811015610905578581018301518582016040015282016108e9565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146107b1575f80fd5b80151581146107b1575f80fd5b5f8060408385031215610982575f80fd5b823561098d81610943565b9150602083013561099d81610964565b809150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156109f557835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016109c3565b50909695505050505050565b5f60208284031215610a11575f80fd5b81356106ef81610943565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a9057610a90610a1c565b604052919050565b5f67ffffffffffffffff821115610ab157610ab1610a1c565b5060051b60200190565b5f6020808385031215610acc575f80fd5b825167ffffffffffffffff80821115610ae3575f80fd5b818501915085601f830112610af6575f80fd5b8151610b09610b0482610a98565b610a49565b818152600591821b8401850191858201919089841115610b27575f80fd5b8686015b84811015610bb957805186811115610b41575f80fd5b8701603f81018c13610b51575f80fd5b888101516040610b63610b0483610a98565b82815291851b83018101918b8101908f841115610b7e575f80fd5b938201935b83851015610ba85784519250610b9883610943565b828252938c0193908c0190610b83565b885250505093880193508701610b2b565b50909998505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156106bf576106bf610bf5565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c6557610c65610bf5565b5060010190565b5f60208284031215610c7c575f80fd5b81516106ef8161096456fea264697066735822122086822f7c8ce08b043cbe7a9b95701703dd494b263875f64663c1fe9ddc41683464736f6c634300081800330000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061006f575f3560e01c80638d5e21d31161004d5780638d5e21d3146100e6578063b9209e33146100fb578063d8a06f731461011e575f80fd5b806306fdde0314610073578063138721d9146100bb5780632e5896e5146100d1575b5f80fd5b604080518082018252601881527f4564676520466163746f72792050657273706563746976650000000000000000602082015290516100b291906108d9565b60405180910390f35b6100c361016a565b6040519081526020016100b2565b6100e46100df366004610971565b6102a6565b005b6100ee6103d0565b6040516100b291906109a8565b61010e610109366004610a01565b61060d565b60405190151581526020016100b2565b6101457f0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a6381565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b2565b6040517fe536913d0000000000000000000000000000000000000000000000000000000081525f600482018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602483015290819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63169063e536913d906044015f60405180830381865afa15801561021c573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526102619190810190610abb565b90505f805b825181101561029f5782818151811061028157610281610bc8565b602002602001015151826102959190610c22565b9150600101610266565b5092915050565b5f8281526002602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815c016102dd57005b6102e75f846106c5565b156102f157505050565b6004805c9060055c9085905d8360055d6001835d61030e856106f6565b5f8260045d8160055d5060035c801561037d576040517f818fa2cf00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff87166024820152604481018290526064015b60405180910390fd5b6103875f876107b4565b5060405173ffffffffffffffffffffffffffffffffffffffff8716907f570e1c1f1f2e6e95bfd6d0cae607f36c3cd5ebb7bc35c2f87299924b1bcd3920905f90a2505050505050565b6040517fe536913d0000000000000000000000000000000000000000000000000000000081525f600482018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602483015260609173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63169063e536913d906044015f60405180830381865afa158015610482573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c79190810190610abb565b90505f805b8251811015610505578281815181106104e7576104e7610bc8565b602002602001015151826104fb9190610c22565b91506001016104cc565b505f8167ffffffffffffffff81111561052057610520610a1c565b604051908082528060200260200182016040528015610549578160200160208202803683370190505b5090505f91505f5b8351811015610605575f5b84828151811061056e5761056e610bc8565b6020026020010151518110156105fc5784828151811061059057610590610bc8565b602002602001015181815181106105a9576105a9610bc8565b60200260200101518385806105bd90610c35565b9650815181106105cf576105cf610bc8565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161055c565b50600101610551565b509392505050565b6040517f90184b0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63909116906390184b0290602401602060405180830381865afa15801561069b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106bf9190610c6c565b92915050565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b9392505050565b6040517f90184b0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526107b1917f0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63909116906390184b0290602401602060405180830381865afa158015610786573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107aa9190610c6c565b60016107d5565b50565b5f6106ef8373ffffffffffffffffffffffffffffffffffffffff841661088d565b81156107df575050565b805f03610818576040517fcb365b8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055c801561087e576040517f818fa2cf000000000000000000000000000000000000000000000000000000008152306004808301919091525c73ffffffffffffffffffffffffffffffffffffffff811660248301526044820184905290606401610374565b60035c82811760035d50505050565b5f8181526001830160205260408120546108d257508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106bf565b505f6106bf565b5f602080835283518060208501525f5b81811015610905578581018301518582016040015282016108e9565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146107b1575f80fd5b80151581146107b1575f80fd5b5f8060408385031215610982575f80fd5b823561098d81610943565b9150602083013561099d81610964565b809150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156109f557835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016109c3565b50909695505050505050565b5f60208284031215610a11575f80fd5b81356106ef81610943565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a9057610a90610a1c565b604052919050565b5f67ffffffffffffffff821115610ab157610ab1610a1c565b5060051b60200190565b5f6020808385031215610acc575f80fd5b825167ffffffffffffffff80821115610ae3575f80fd5b818501915085601f830112610af6575f80fd5b8151610b09610b0482610a98565b610a49565b818152600591821b8401850191858201919089841115610b27575f80fd5b8686015b84811015610bb957805186811115610b41575f80fd5b8701603f81018c13610b51575f80fd5b888101516040610b63610b0483610a98565b82815291851b83018101918b8101908f841115610b7e575f80fd5b938201935b83851015610ba85784519250610b9883610943565b828252938c0193908c0190610b83565b885250505093880193508701610b2b565b50909998505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156106bf576106bf610bf5565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c6557610c65610bf5565b5060010190565b5f60208284031215610c7c575f80fd5b81516106ef8161096456fea264697066735822122086822f7c8ce08b043cbe7a9b95701703dd494b263875f64663c1fe9ddc41683464736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63
-----Decoded View---------------
Arg [0] : edgeFactory_ (address): 0x0ddcB0a765D09D86E526dE7a9839398159274A63
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000ddcb0a765d09d86e526de7a9839398159274a63
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.