Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 10 from a total of 10 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Vault | 21191305 | 8 days ago | IN | 0 ETH | 0.00714451 | ||||
Create Vault | 20870906 | 52 days ago | IN | 0 ETH | 0.00596523 | ||||
Create Vault | 20866323 | 53 days ago | IN | 0 ETH | 0.00737041 | ||||
Create Vault | 20849579 | 55 days ago | IN | 0 ETH | 0.0039844 | ||||
Create Vault | 20820236 | 59 days ago | IN | 0 ETH | 0.00522988 | ||||
Create Vault | 20710932 | 75 days ago | IN | 0 ETH | 0.00074776 | ||||
Create Vault | 20705958 | 75 days ago | IN | 0 ETH | 0.00072222 | ||||
Create Vault | 20654901 | 83 days ago | IN | 0 ETH | 0.00030216 | ||||
Create Vault | 20640226 | 85 days ago | IN | 0 ETH | 0.00036745 | ||||
0x60c03461 | 20236221 | 141 days ago | IN | 0 ETH | 0.00217575 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
21191305 | 8 days ago | 0 ETH | ||||
21191305 | 8 days ago | Contract Creation | 0 ETH | |||
21191305 | 8 days ago | Contract Creation | 0 ETH | |||
20870906 | 52 days ago | 0 ETH | ||||
20870906 | 52 days ago | Contract Creation | 0 ETH | |||
20866323 | 53 days ago | 0 ETH | ||||
20866323 | 53 days ago | Contract Creation | 0 ETH | |||
20866323 | 53 days ago | Contract Creation | 0 ETH | |||
20849579 | 55 days ago | 0 ETH | ||||
20849579 | 55 days ago | Contract Creation | 0 ETH | |||
20849579 | 55 days ago | Contract Creation | 0 ETH | |||
20820236 | 59 days ago | 0 ETH | ||||
20820236 | 59 days ago | Contract Creation | 0 ETH | |||
20710932 | 75 days ago | 0 ETH | ||||
20710932 | 75 days ago | Contract Creation | 0 ETH | |||
20705958 | 75 days ago | 0 ETH | ||||
20705958 | 75 days ago | Contract Creation | 0 ETH | |||
20654901 | 83 days ago | 0 ETH | ||||
20654901 | 83 days ago | Contract Creation | 0 ETH | |||
20654901 | 83 days ago | Contract Creation | 0 ETH | |||
20640226 | 85 days ago | 0 ETH | ||||
20640226 | 85 days ago | Contract Creation | 0 ETH | |||
20634347 | 85 days ago | 0 ETH | ||||
20634347 | 85 days ago | Contract Creation | 0 ETH | |||
20634347 | 85 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
EthVaultFactory
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {ERC1967Proxy} from '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol'; import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; import {IEthVault} from '../../interfaces/IEthVault.sol'; import {IVaultsRegistry} from '../../interfaces/IVaultsRegistry.sol'; import {OwnMevEscrow} from './mev/OwnMevEscrow.sol'; /** * @title EthVaultFactory * @author StakeWise * @notice Factory for deploying Ethereum staking Vaults */ contract EthVaultFactory is IEthVaultFactory { IVaultsRegistry internal immutable _vaultsRegistry; /// @inheritdoc IEthVaultFactory address public immutable override implementation; /// @inheritdoc IEthVaultFactory address public override ownMevEscrow; /// @inheritdoc IEthVaultFactory address public override vaultAdmin; /** * @dev Constructor * @param _implementation The implementation address of Vault * @param vaultsRegistry The address of the VaultsRegistry contract */ constructor(address _implementation, IVaultsRegistry vaultsRegistry) { implementation = _implementation; _vaultsRegistry = vaultsRegistry; } /// @inheritdoc IEthVaultFactory function createVault( bytes calldata params, bool isOwnMevEscrow ) external payable override returns (address vault) { // create vault vault = address(new ERC1967Proxy(implementation, '')); // create MEV escrow contract if needed address _mevEscrow; if (isOwnMevEscrow) { _mevEscrow = address(new OwnMevEscrow(vault)); // set MEV escrow contract so that it can be initialized in the Vault ownMevEscrow = _mevEscrow; } // set admin so that it can be initialized in the Vault vaultAdmin = msg.sender; // initialize Vault IEthVault(vault).initialize{value: msg.value}(params); // cleanup MEV escrow contract if (isOwnMevEscrow) delete ownMevEscrow; // cleanup admin delete vaultAdmin; // add vault to the registry _vaultsRegistry.addVault(vault); // emit event emit VaultCreated(msg.sender, vault, _mevEscrow, params); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.20; import {Proxy} from "../Proxy.sol"; import {ERC1967Utils} from "./ERC1967Utils.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`. * * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. * * Requirements: * * - If `data` is empty, `msg.value` must be zero. */ constructor(address implementation, bytes memory _data) payable { ERC1967Utils.upgradeToAndCall(implementation, _data); } /** * @dev Returns the current implementation address. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _implementation() internal view virtual override returns (address) { return ERC1967Utils.getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol) pragma solidity ^0.8.20; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback * function and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; import {IVaultVersion} from './IVaultVersion.sol'; import {IVaultFee} from './IVaultFee.sol'; import {IVaultState} from './IVaultState.sol'; import {IVaultValidators} from './IVaultValidators.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; import {IVaultOsToken} from './IVaultOsToken.sol'; import {IVaultMev} from './IVaultMev.sol'; import {IVaultEthStaking} from './IVaultEthStaking.sol'; import {IMulticall} from './IMulticall.sol'; /** * @title IEthVault * @author StakeWise * @notice Defines the interface for the EthVault contract */ interface IEthVault is IVaultAdmin, IVaultVersion, IVaultFee, IVaultState, IVaultValidators, IVaultEnterExit, IVaultOsToken, IVaultMev, IVaultEthStaking, IMulticall { /** * @dev Struct for initializing the EthVault contract * @param capacity The Vault stops accepting deposits after exceeding the capacity * @param feePercent The fee percent that is charged by the Vault * @param metadataIpfsHash The IPFS hash of the Vault's metadata file */ struct EthVaultInitParams { uint256 capacity; uint16 feePercent; string metadataIpfsHash; } /** * @notice Initializes or upgrades the EthVault contract. Must transfer security deposit during the deployment. * @param params The encoded parameters for initializing the EthVault contract */ function initialize(bytes calldata params) external payable; /** * @notice Deposits assets to the vault and mints OsToken shares to the receiver * @param receiver The address to receive the OsToken * @param osTokenShares The amount of OsToken shares to mint. * If set to type(uint256).max, max OsToken shares will be minted based on the deposited amount. * @param referrer The address of the referrer * @return The amount of OsToken shares minted */ function depositAndMintOsToken( address receiver, uint256 osTokenShares, address referrer ) external payable returns (uint256); /** * @notice Updates the state, deposits assets to the vault and mints OsToken shares to the receiver * @param receiver The address to receive the OsToken * @param osTokenShares The amount of OsToken shares to mint. * If set to type(uint256).max, max OsToken shares will be minted based on the deposited amount. * @param referrer The address of the referrer * @param harvestParams The parameters for the harvest * @return The amount of OsToken shares minted */ function updateStateAndDepositAndMintOsToken( address receiver, uint256 osTokenShares, address referrer, IKeeperRewards.HarvestParams calldata harvestParams ) external payable returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IEthVaultFactory * @author StakeWise * @notice Defines the interface for the ETH Vault Factory contract */ interface IEthVaultFactory { /** * @notice Event emitted on a Vault creation * @param admin The address of the Vault admin * @param vault The address of the created Vault * @param ownMevEscrow The address of the own MEV escrow contract. Zero address if shared MEV escrow is used. * @param params The encoded parameters for initializing the Vault contract */ event VaultCreated( address indexed admin, address indexed vault, address ownMevEscrow, bytes params ); /** * @notice The address of the Vault implementation contract used for proxy creation * @return The address of the Vault implementation contract */ function implementation() external view returns (address); /** * @notice The address of the own MEV escrow contract used for Vault creation * @return The address of the MEV escrow contract */ function ownMevEscrow() external view returns (address); /** * @notice The address of the Vault admin used for Vault creation * @return The address of the Vault admin */ function vaultAdmin() external view returns (address); /** * @notice Create Vault. Must transfer security deposit together with a call. * @param params The encoded parameters for initializing the Vault contract * @param isOwnMevEscrow Whether to deploy own escrow contract or connect to a smoothing pool for priority fees and MEV rewards * @return vault The address of the created Vault */ function createVault( bytes calldata params, bool isOwnMevEscrow ) external payable returns (address vault); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IERC5267} from '@openzeppelin/contracts/interfaces/IERC5267.sol'; /** * @title IKeeperOracles * @author StakeWise * @notice Defines the interface for the KeeperOracles contract */ interface IKeeperOracles is IERC5267 { /** * @notice Event emitted on the oracle addition * @param oracle The address of the added oracle */ event OracleAdded(address indexed oracle); /** * @notice Event emitted on the oracle removal * @param oracle The address of the removed oracle */ event OracleRemoved(address indexed oracle); /** * @notice Event emitted on oracles config update * @param configIpfsHash The IPFS hash of the new config */ event ConfigUpdated(string configIpfsHash); /** * @notice Function for verifying whether oracle is registered or not * @param oracle The address of the oracle to check * @return `true` for the registered oracle, `false` otherwise */ function isOracle(address oracle) external view returns (bool); /** * @notice Total Oracles * @return The total number of oracles registered */ function totalOracles() external view returns (uint256); /** * @notice Function for adding oracle to the set * @param oracle The address of the oracle to add */ function addOracle(address oracle) external; /** * @notice Function for removing oracle from the set * @param oracle The address of the oracle to remove */ function removeOracle(address oracle) external; /** * @notice Function for updating the config IPFS hash * @param configIpfsHash The new config IPFS hash */ function updateConfig(string calldata configIpfsHash) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperOracles} from './IKeeperOracles.sol'; /** * @title IKeeperRewards * @author StakeWise * @notice Defines the interface for the Keeper contract rewards */ interface IKeeperRewards is IKeeperOracles { /** * @notice Event emitted on rewards update * @param caller The address of the function caller * @param rewardsRoot The new rewards merkle tree root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param nonce The nonce used for verifying signatures * @param rewardsIpfsHash The new rewards IPFS hash */ event RewardsUpdated( address indexed caller, bytes32 indexed rewardsRoot, uint256 avgRewardPerSecond, uint64 updateTimestamp, uint64 nonce, string rewardsIpfsHash ); /** * @notice Event emitted on Vault harvest * @param vault The address of the Vault * @param rewardsRoot The rewards merkle tree root * @param totalAssetsDelta The Vault total assets delta since last sync. Can be negative in case of penalty/slashing. * @param unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. */ event Harvested( address indexed vault, bytes32 indexed rewardsRoot, int256 totalAssetsDelta, uint256 unlockedMevDelta ); /** * @notice Event emitted on rewards min oracles number update * @param oracles The new minimum number of oracles required to update rewards */ event RewardsMinOraclesUpdated(uint256 oracles); /** * @notice A struct containing the last synced Vault's cumulative reward * @param assets The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param nonce The nonce of the last sync */ struct Reward { int192 assets; uint64 nonce; } /** * @notice A struct containing the last unlocked Vault's cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param assets The shared MEV Vault's cumulative execution reward that can be withdrawn * @param nonce The nonce of the last sync */ struct UnlockedMevReward { uint192 assets; uint64 nonce; } /** * @notice A struct containing parameters for rewards update * @param rewardsRoot The new rewards merkle root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param rewardsIpfsHash The new IPFS hash with all the Vaults' rewards for the new root * @param signatures The concatenation of the Oracles' signatures */ struct RewardsUpdateParams { bytes32 rewardsRoot; uint256 avgRewardPerSecond; uint64 updateTimestamp; string rewardsIpfsHash; bytes signatures; } /** * @notice A struct containing parameters for harvesting rewards. Can only be called by Vault. * @param rewardsRoot The rewards merkle root * @param reward The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param unlockedMevReward The Vault cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param proof The proof to verify that Vault's reward is correct */ struct HarvestParams { bytes32 rewardsRoot; int160 reward; uint160 unlockedMevReward; bytes32[] proof; } /** * @notice Previous Rewards Root * @return The previous merkle tree root of the rewards accumulated by the Vaults */ function prevRewardsRoot() external view returns (bytes32); /** * @notice Rewards Root * @return The latest merkle tree root of the rewards accumulated by the Vaults */ function rewardsRoot() external view returns (bytes32); /** * @notice Rewards Nonce * @return The nonce used for updating rewards merkle tree root */ function rewardsNonce() external view returns (uint64); /** * @notice The last rewards update * @return The timestamp of the last rewards update */ function lastRewardsTimestamp() external view returns (uint64); /** * @notice The minimum number of oracles required to update rewards * @return The minimum number of oracles */ function rewardsMinOracles() external view returns (uint256); /** * @notice The rewards delay * @return The delay in seconds between rewards updates */ function rewardsDelay() external view returns (uint256); /** * @notice Get last synced Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function rewards(address vault) external view returns (int192 assets, uint64 nonce); /** * @notice Get last unlocked shared MEV Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function unlockedMevRewards(address vault) external view returns (uint192 assets, uint64 nonce); /** * @notice Checks whether Vault must be harvested * @param vault The address of the Vault * @return `true` if the Vault requires harvesting, `false` otherwise */ function isHarvestRequired(address vault) external view returns (bool); /** * @notice Checks whether the Vault can be harvested * @param vault The address of the Vault * @return `true` if Vault can be harvested, `false` otherwise */ function canHarvest(address vault) external view returns (bool); /** * @notice Checks whether rewards can be updated * @return `true` if rewards can be updated, `false` otherwise */ function canUpdateRewards() external view returns (bool); /** * @notice Checks whether the Vault has registered validators * @param vault The address of the Vault * @return `true` if Vault is collateralized, `false` otherwise */ function isCollateralized(address vault) external view returns (bool); /** * @notice Update rewards data * @param params The struct containing rewards update parameters */ function updateRewards(RewardsUpdateParams calldata params) external; /** * @notice Harvest rewards. Can be called only by Vault. * @param params The struct containing rewards harvesting parameters * @return totalAssetsDelta The total reward/penalty accumulated by the Vault since the last sync * @return unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @return harvested `true` when the rewards were harvested, `false` otherwise */ function harvest( HarvestParams calldata params ) external returns (int256 totalAssetsDelta, uint256 unlockedMevDelta, bool harvested); /** * @notice Set min number of oracles for confirming rewards update. Can only be called by the owner. * @param _rewardsMinOracles The new min number of oracles for confirming rewards update */ function setRewardsMinOracles(uint256 _rewardsMinOracles) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IKeeperOracles} from './IKeeperOracles.sol'; /** * @title IKeeperValidators * @author StakeWise * @notice Defines the interface for the Keeper validators */ interface IKeeperValidators is IKeeperOracles, IKeeperRewards { /** * @notice Event emitted on validators approval * @param vault The address of the Vault * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ event ValidatorsApproval(address indexed vault, string exitSignaturesIpfsHash); /** * @notice Event emitted on exit signatures update * @param caller The address of the function caller * @param vault The address of the Vault * @param nonce The nonce used for verifying Oracles' signatures * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ event ExitSignaturesUpdated( address indexed caller, address indexed vault, uint256 nonce, string exitSignaturesIpfsHash ); /** * @notice Event emitted on validators min oracles number update * @param oracles The new minimum number of oracles required to approve validators */ event ValidatorsMinOraclesUpdated(uint256 oracles); /** * @notice Get nonce for the next vault exit signatures update * @param vault The address of the Vault to get the nonce for * @return The nonce of the Vault for updating signatures */ function exitSignaturesNonces(address vault) external view returns (uint256); /** * @notice Struct for approving registration of one or more validators * @param validatorsRegistryRoot The deposit data root used to verify that oracles approved validators * @param deadline The deadline for submitting the approval * @param validators The concatenation of the validators' public key, signature and deposit data root * @param signatures The concatenation of Oracles' signatures * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures */ struct ApprovalParams { bytes32 validatorsRegistryRoot; uint256 deadline; bytes validators; bytes signatures; string exitSignaturesIpfsHash; } /** * @notice The minimum number of oracles required to update validators * @return The minimum number of oracles */ function validatorsMinOracles() external view returns (uint256); /** * @notice Function for approving validators registration * @param params The parameters for approving validators registration */ function approveValidators(ApprovalParams calldata params) external; /** * @notice Function for updating exit signatures for every hard fork * @param vault The address of the Vault to update signatures for * @param deadline The deadline for submitting signatures update * @param exitSignaturesIpfsHash The IPFS hash with the validators' exit signatures * @param oraclesSignatures The concatenation of Oracles' signatures */ function updateExitSignatures( address vault, uint256 deadline, string calldata exitSignaturesIpfsHash, bytes calldata oraclesSignatures ) external; /** * @notice Function for updating validators min oracles number * @param _validatorsMinOracles The new minimum number of oracles required to approve validators */ function setValidatorsMinOracles(uint256 _validatorsMinOracles) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.22; /** * @title Multicall * @author Uniswap * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol * @notice Enables calling multiple methods in a single call to the contract */ interface IMulticall { /** * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed * @param data The encoded function data for each of the calls to make to this contract * @return results The results from each of the calls passed in via data */ function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOwnMevEscrow * @author StakeWise * @notice Defines the interface for the OwnMevEscrow contract */ interface IOwnMevEscrow { /** * @notice Event emitted on received MEV * @param assets The amount of MEV assets received */ event MevReceived(uint256 assets); /** * @notice Event emitted on harvest * @param assets The amount of assets withdrawn */ event Harvested(uint256 assets); /** * @notice Vault address * @return The address of the vault that owns the escrow */ function vault() external view returns (address payable); /** * @notice Withdraws MEV accumulated in the escrow. Can be called only by the Vault. * @dev IMPORTANT: because control is transferred to the Vault, care must be * taken to not create reentrancy vulnerabilities. The Vault must follow the checks-effects-interactions pattern: * https://docs.soliditylang.org/en/v0.8.22/security-considerations.html#use-the-checks-effects-interactions-pattern * @return assets The amount of assets withdrawn */ function harvest() external returns (uint256 assets); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultAdmin contract */ interface IVaultAdmin { /** * @notice Event emitted on metadata ipfs hash update * @param caller The address of the function caller * @param metadataIpfsHash The new metadata IPFS hash */ event MetadataUpdated(address indexed caller, string metadataIpfsHash); /** * @notice The Vault admin * @return The address of the Vault admin */ function admin() external view returns (address); /** * @notice Function for updating the metadata IPFS hash. Can only be called by Vault admin. * @param metadataIpfsHash The new metadata IPFS hash */ function setMetadata(string calldata metadataIpfsHash) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultEnterExit * @author StakeWise * @notice Defines the interface for the VaultEnterExit contract */ interface IVaultEnterExit is IVaultState { /** * @notice Event emitted on deposit * @param caller The address that called the deposit function * @param receiver The address that received the shares * @param assets The number of assets deposited by the caller * @param shares The number of shares received * @param referrer The address of the referrer */ event Deposited( address indexed caller, address indexed receiver, uint256 assets, uint256 shares, address referrer ); /** * @notice Event emitted on redeem (deprecated) * @param owner The address that owns the shares * @param receiver The address that received withdrawn assets * @param assets The total number of withdrawn assets * @param shares The total number of withdrawn shares */ event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); /** * @notice Event emitted on shares added to the V1 exit queue (deprecated) * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit */ event ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares ); /** * @notice Event emitted on shares added to the V2 exit queue * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit * @param assets The number of assets that queued for the exit */ event V2ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares, uint256 assets ); /** * @notice Event emitted on claim of the exited assets * @param receiver The address that has received withdrawn assets * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call * @param newPositionTicket The new exit queue ticket in case not all the assets were withdrawn. Otherwise 0. * @param withdrawnAssets The total number of assets withdrawn */ event ExitedAssetsClaimed( address indexed receiver, uint256 prevPositionTicket, uint256 newPositionTicket, uint256 withdrawnAssets ); /** * @notice Locks assets to the exit queue. The shares to assets rate will be locked at the moment of the call. * @param shares The number of shares to exit * @param receiver The address that will receive assets upon withdrawal * @return positionTicket The position ticket of the exit queue */ function enterExitQueue( uint256 shares, address receiver ) external returns (uint256 positionTicket); /** * @notice Get the exit queue index to claim exited assets from (deprecated) * @param positionTicket The exit queue position ticket to get the index for * @return The exit queue index that should be used to claim exited assets. * Returns -1 in case such index does not exist. */ function getExitQueueIndex(uint256 positionTicket) external view returns (int256); /** * @notice Calculates the number of assets that can be claimed from the exit queue. * @param receiver The address that will receive assets upon withdrawal * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the assets entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. * It can be looked up by calling `getExitQueueIndex`. Only relevant for V1 positions, otherwise pass 0. * @return leftTickets The number of tickets left in the queue * @return exitedTickets The number of tickets that have already exited * @return exitedAssets The number of assets that can be claimed */ function calculateExitedAssets( address receiver, uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external view returns (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets); /** * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`. * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the assets entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. * It can be looked up by calling `getExitQueueIndex`. Only relevant for V1 positions, otherwise pass 0. */ function claimExitedAssets( uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; import {IVaultValidators} from './IVaultValidators.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultMev} from './IVaultMev.sol'; /** * @title IVaultEthStaking * @author StakeWise * @notice Defines the interface for the VaultEthStaking contract */ interface IVaultEthStaking is IVaultState, IVaultValidators, IVaultEnterExit, IVaultMev { /** * @notice Deposit ETH to the Vault * @param receiver The address that will receive Vault's shares * @param referrer The address of the referrer. Set to zero address if not used. * @return shares The number of shares minted */ function deposit(address receiver, address referrer) external payable returns (uint256 shares); /** * @notice Used by MEV escrow to transfer ETH. */ function receiveFromMevEscrow() external payable; /** * @notice Updates Vault state and deposits ETH to the Vault * @param receiver The address that will receive Vault's shares * @param referrer The address of the referrer. Set to zero address if not used. * @param harvestParams The parameters for harvesting Keeper rewards * @return shares The number of shares minted */ function updateStateAndDeposit( address receiver, address referrer, IKeeperRewards.HarvestParams calldata harvestParams ) external payable returns (uint256 shares); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultAdmin} from './IVaultAdmin.sol'; /** * @title IVaultFee * @author StakeWise * @notice Defines the interface for the VaultFee contract */ interface IVaultFee is IVaultAdmin { /** * @notice Event emitted on fee recipient update * @param caller The address of the function caller * @param feeRecipient The address of the new fee recipient */ event FeeRecipientUpdated(address indexed caller, address indexed feeRecipient); /** * @notice The Vault's fee recipient * @return The address of the Vault's fee recipient */ function feeRecipient() external view returns (address); /** * @notice The Vault's fee percent in BPS * @return The fee percent applied by the Vault on the rewards */ function feePercent() external view returns (uint16); /** * @notice Function for updating the fee recipient address. Can only be called by the admin. * @param _feeRecipient The address of the new fee recipient */ function setFeeRecipient(address _feeRecipient) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultMev * @author StakeWise * @notice Common interface for the VaultMev contracts */ interface IVaultMev is IVaultState { /** * @notice The contract that accumulates MEV rewards * @return The MEV escrow contract address */ function mevEscrow() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; import {IVaultEnterExit} from './IVaultEnterExit.sol'; /** * @title IVaultOsToken * @author StakeWise * @notice Defines the interface for the VaultOsToken contract */ interface IVaultOsToken is IVaultState, IVaultEnterExit { /** * @notice Event emitted on minting osToken * @param caller The address of the function caller * @param receiver The address of the osToken receiver * @param assets The amount of minted assets * @param shares The amount of minted shares * @param referrer The address of the referrer */ event OsTokenMinted( address indexed caller, address receiver, uint256 assets, uint256 shares, address referrer ); /** * @notice Event emitted on burning OsToken * @param caller The address of the function caller * @param assets The amount of burned assets * @param shares The amount of burned shares */ event OsTokenBurned(address indexed caller, uint256 assets, uint256 shares); /** * @notice Event emitted on osToken position liquidation * @param caller The address of the function caller * @param user The address of the user liquidated * @param receiver The address of the receiver of the liquidated assets * @param osTokenShares The amount of osToken shares to liquidate * @param shares The amount of vault shares burned * @param receivedAssets The amount of assets received */ event OsTokenLiquidated( address indexed caller, address indexed user, address receiver, uint256 osTokenShares, uint256 shares, uint256 receivedAssets ); /** * @notice Event emitted on osToken position redemption * @param caller The address of the function caller * @param user The address of the position owner to redeem from * @param receiver The address of the receiver of the redeemed assets * @param osTokenShares The amount of osToken shares to redeem * @param shares The amount of vault shares burned * @param assets The amount of assets received */ event OsTokenRedeemed( address indexed caller, address indexed user, address receiver, uint256 osTokenShares, uint256 shares, uint256 assets ); /** * @notice Struct of osToken position * @param shares The total number of minted osToken shares. Will increase based on the treasury fee. * @param cumulativeFeePerShare The cumulative fee per share */ struct OsTokenPosition { uint128 shares; uint128 cumulativeFeePerShare; } /** * @notice Get total amount of minted osToken shares * @param user The address of the user * @return shares The number of minted osToken shares */ function osTokenPositions(address user) external view returns (uint128 shares); /** * @notice Mints OsToken shares * @param receiver The address that will receive the minted OsToken shares * @param osTokenShares The number of OsToken shares to mint to the receiver * @param referrer The address of the referrer * @return assets The number of assets minted to the receiver */ function mintOsToken( address receiver, uint256 osTokenShares, address referrer ) external returns (uint256 assets); /** * @notice Burns osToken shares * @param osTokenShares The number of shares to burn * @return assets The number of assets burned */ function burnOsToken(uint128 osTokenShares) external returns (uint256 assets); /** * @notice Liquidates a user position and returns the number of received assets. * Can only be called when health factor is below 1 by the liquidator. * @param osTokenShares The number of shares to cover * @param owner The address of the position owner to liquidate * @param receiver The address of the receiver of the liquidated assets */ function liquidateOsToken(uint256 osTokenShares, address owner, address receiver) external; /** * @notice Redeems osToken shares for assets. Can only be called when health factor is above redeemFromHealthFactor by the redeemer. * @param osTokenShares The number of osToken shares to redeem * @param owner The address of the position owner to redeem from * @param receiver The address of the receiver of the redeemed assets */ function redeemOsToken(uint256 osTokenShares, address owner, address receiver) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IVaultsRegistry * @author StakeWise * @notice Defines the interface for the VaultsRegistry */ interface IVaultsRegistry { /** * @notice Event emitted on a Vault addition * @param caller The address that has added the Vault * @param vault The address of the added Vault */ event VaultAdded(address indexed caller, address indexed vault); /** * @notice Event emitted on adding Vault implementation contract * @param impl The address of the new implementation contract */ event VaultImplAdded(address indexed impl); /** * @notice Event emitted on removing Vault implementation contract * @param impl The address of the removed implementation contract */ event VaultImplRemoved(address indexed impl); /** * @notice Event emitted on whitelisting the factory * @param factory The address of the whitelisted factory */ event FactoryAdded(address indexed factory); /** * @notice Event emitted on removing the factory from the whitelist * @param factory The address of the factory removed from the whitelist */ event FactoryRemoved(address indexed factory); /** * @notice Registered Vaults * @param vault The address of the vault to check whether it is registered * @return `true` for the registered Vault, `false` otherwise */ function vaults(address vault) external view returns (bool); /** * @notice Registered Vault implementations * @param impl The address of the vault implementation * @return `true` for the registered implementation, `false` otherwise */ function vaultImpls(address impl) external view returns (bool); /** * @notice Registered Factories * @param factory The address of the factory to check whether it is whitelisted * @return `true` for the whitelisted Factory, `false` otherwise */ function factories(address factory) external view returns (bool); /** * @notice Function for adding Vault to the registry. Can only be called by the whitelisted Factory. * @param vault The address of the Vault to add */ function addVault(address vault) external; /** * @notice Function for adding Vault implementation contract * @param newImpl The address of the new implementation contract */ function addVaultImpl(address newImpl) external; /** * @notice Function for removing Vault implementation contract * @param impl The address of the removed implementation contract */ function removeVaultImpl(address impl) external; /** * @notice Function for adding the factory to the whitelist * @param factory The address of the factory to add to the whitelist */ function addFactory(address factory) external; /** * @notice Function for removing the factory from the whitelist * @param factory The address of the factory to remove from the whitelist */ function removeFactory(address factory) external; /** * @notice Function for initializing the registry. Can only be called once during the deployment. * @param _owner The address of the owner of the contract */ function initialize(address _owner) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultFee} from './IVaultFee.sol'; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultState contract */ interface IVaultState is IVaultFee { /** * @notice Event emitted on checkpoint creation (deprecated) * @param shares The number of burned shares * @param assets The amount of exited assets */ event CheckpointCreated(uint256 shares, uint256 assets); /** * @notice Event emitted on minting fee recipient shares * @param receiver The address of the fee recipient * @param shares The number of minted shares * @param assets The amount of minted assets */ event FeeSharesMinted(address receiver, uint256 shares, uint256 assets); /** * @notice Event emitted when exiting assets are penalized * @param penalty The total penalty amount */ event ExitingAssetsPenalized(uint256 penalty); /** * @notice Total assets in the Vault * @return The total amount of the underlying asset that is "managed" by Vault */ function totalAssets() external view returns (uint256); /** * @notice Function for retrieving total shares * @return The amount of shares in existence */ function totalShares() external view returns (uint256); /** * @notice The Vault's capacity * @return The amount after which the Vault stops accepting deposits */ function capacity() external view returns (uint256); /** * @notice Total assets available in the Vault. They can be staked or withdrawn. * @return The total amount of withdrawable assets */ function withdrawableAssets() external view returns (uint256); /** * @notice Queued Shares (deprecated) * @return The total number of shares queued for exit */ function queuedShares() external view returns (uint128); /** * @notice Total Exiting Assets * @return The total number of assets queued for exit */ function totalExitingAssets() external view returns (uint128); /** * @notice Returns the number of shares held by an account * @param account The account for which to look up the number of shares it has, i.e. its balance * @return The number of shares held by the account */ function getShares(address account) external view returns (uint256); /** * @notice Converts shares to assets * @param assets The amount of assets to convert to shares * @return shares The amount of shares that the Vault would exchange for the amount of assets provided */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @notice Converts assets to shares * @param shares The amount of shares to convert to assets * @return assets The amount of assets that the Vault would exchange for the amount of shares provided */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @notice Check whether state update is required * @return `true` if state update is required, `false` otherwise */ function isStateUpdateRequired() external view returns (bool); /** * @notice Updates the total amount of assets in the Vault and its exit queue * @param harvestParams The parameters for harvesting Keeper rewards */ function updateState(IKeeperRewards.HarvestParams calldata harvestParams) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperValidators} from './IKeeperValidators.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultValidators * @author StakeWise * @notice Defines the interface for VaultValidators contract */ interface IVaultValidators is IVaultAdmin, IVaultState { /** * @notice Event emitted on validator registration * @param publicKey The public key of the validator that was registered */ event ValidatorRegistered(bytes publicKey); /** * @notice Event emitted on keys manager address update (deprecated) * @param caller The address of the function caller * @param keysManager The address of the new keys manager */ event KeysManagerUpdated(address indexed caller, address indexed keysManager); /** * @notice Event emitted on validators merkle tree root update (deprecated) * @param caller The address of the function caller * @param validatorsRoot The new validators merkle tree root */ event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot); /** * @notice Event emitted on validators manager address update * @param caller The address of the function caller * @param validatorsManager The address of the new validators manager */ event ValidatorsManagerUpdated(address indexed caller, address indexed validatorsManager); /** * @notice The Vault validators manager address * @return The address that can register validators */ function validatorsManager() external view returns (address); /** * @notice Function for registering single or multiple validators * @param keeperParams The parameters for getting approval from Keeper oracles * @param validatorsManagerSignature The optional signature from the validators manager */ function registerValidators( IKeeperValidators.ApprovalParams calldata keeperParams, bytes calldata validatorsManagerSignature ) external; /** * @notice Function for updating the validators manager. Can only be called by the admin. Default is the DepositDataRegistry contract. * @param _validatorsManager The new validators manager address */ function setValidatorsManager(address _validatorsManager) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IERC1822Proxiable} from '@openzeppelin/contracts/interfaces/draft-IERC1822.sol'; import {IVaultAdmin} from './IVaultAdmin.sol'; /** * @title IVaultVersion * @author StakeWise * @notice Defines the interface for VaultVersion contract */ interface IVaultVersion is IERC1822Proxiable, IVaultAdmin { /** * @notice Vault Unique Identifier * @return The unique identifier of the Vault */ function vaultId() external pure returns (bytes32); /** * @notice Version * @return The version of the Vault implementation contract */ function version() external pure returns (uint8); /** * @notice Implementation * @return The address of the Vault implementation contract */ function implementation() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title Errors * @author StakeWise * @notice Contains all the custom errors */ library Errors { error AccessDenied(); error InvalidShares(); error InvalidAssets(); error ZeroAddress(); error InsufficientAssets(); error CapacityExceeded(); error InvalidCapacity(); error InvalidSecurityDeposit(); error InvalidFeeRecipient(); error InvalidFeePercent(); error NotHarvested(); error NotCollateralized(); error InvalidProof(); error LowLtv(); error RedemptionExceeded(); error InvalidPosition(); error InvalidLtv(); error InvalidHealthFactor(); error InvalidReceivedAssets(); error InvalidTokenMeta(); error UpgradeFailed(); error InvalidValidators(); error DeadlineExpired(); error PermitInvalidSigner(); error InvalidValidatorsRegistryRoot(); error InvalidVault(); error AlreadyAdded(); error AlreadyRemoved(); error InvalidOracles(); error NotEnoughSignatures(); error InvalidOracle(); error TooEarlyUpdate(); error InvalidAvgRewardPerSecond(); error InvalidRewardsRoot(); error HarvestFailed(); error LiquidationDisabled(); error InvalidLiqThresholdPercent(); error InvalidLiqBonusPercent(); error InvalidLtvPercent(); error InvalidCheckpointIndex(); error InvalidCheckpointValue(); error MaxOraclesExceeded(); error ExitRequestNotProcessed(); error ValueNotChanged(); error EigenInvalidWithdrawal(); error InvalidEigenQueuedWithdrawals(); error InvalidWithdrawalCredentials(); error EigenPodNotFound(); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IOwnMevEscrow} from '../../../interfaces/IOwnMevEscrow.sol'; import {IVaultEthStaking} from '../../../interfaces/IVaultEthStaking.sol'; import {Errors} from '../../../libraries/Errors.sol'; /** * @title OwnMevEscrow * @author StakeWise * @notice Accumulates received MEV. The escrow is owned by the Vault. */ contract OwnMevEscrow is IOwnMevEscrow { address payable public immutable override vault; /// @dev Constructor constructor(address _vault) { vault = payable(_vault); } /// @inheritdoc IOwnMevEscrow function harvest() external returns (uint256 assets) { if (msg.sender != vault) revert Errors.HarvestFailed(); assets = address(this).balance; if (assets == 0) return 0; emit Harvested(assets); // slither-disable-next-line arbitrary-send-eth IVaultEthStaking(msg.sender).receiveFromMevEscrow{value: assets}(); } /** * @dev Function for receiving MEV */ receive() external payable { emit MevReceived(msg.value); } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 200, "details": { "yul": true } }, "evmVersion": "shanghai", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_implementation","type":"address"},{"internalType":"contract IVaultsRegistry","name":"vaultsRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"ownMevEscrow","type":"address"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"VaultCreated","type":"event"},{"inputs":[{"internalType":"bytes","name":"params","type":"bytes"},{"internalType":"bool","name":"isOwnMevEscrow","type":"bool"}],"name":"createVault","outputs":[{"internalType":"address","name":"vault","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownMevEscrow","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c03461008b57601f6109c238819003918201601f19168301916001600160401b0383118484101761008f57808492604094855283398101031261008b5780516001600160a01b0391828216820361008b5760200151918216820361008b5760a05260805260405161091e90816100a48239608051816101a9015260a05181818160f9015261034b0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080604081815260049182361015610015575f80fd5b5f925f3560e01c9182635c60da1b14610339575081636f4fa30f146103125781639a0d79ad14610079575063e7f6f2251461004e575f80fd5b3461007557816003193601126100755760015490516001600160a01b039091168152602090f35b5080fd5b918091506003193601126102925781359267ffffffffffffffff928385116102925736602386011215610292578481013594848611610292576024928382019184883692010111610292578335928315158403610292578551946102c895868101968188108a891117610300576103c3823960608160018060a01b0398897f00000000000000000000000000000000000000000000000000000000000000001681528a60208201525f8b8201520301905ff080156102e45786869116985f96610296575b506bffffffffffffffffffffffff60a01b9033826001541617600155893b15610292576101885f878c8e8d5180958194829363439fab9160e01b845260208d8501528b8401916103a2565b039134905af1801561028857610275575b5061026a575b60015416600155857f00000000000000000000000000000000000000000000000000000000000000001691823b156102665783918991838a5195869485936312b5ad0160e11b85528401525af1801561025c57610245575b505084926020969261023c7f0d606510f33b5e566ed1ca2b9e88d388ab81cea532909665d725b33134516aff938751938493168352878a8401523395888401916103a2565b0390a351908152f35b61024f829161037a565b61025957806101f7565b80fd5b86513d84823e3d90fd5b8380fd5b80845416845561019f565b61028091955061037a565b5f935f610199565b8a513d5f823e3d90fd5b5f80fd5b885191965061025e808301918211838310176102ee57602091839161068b83398b81520301905ff080156102e457861694856bffffffffffffffffffffffff60a01b5f5416175f555f61013d565b87513d5f823e3d90fd5b83604186634e487b7160e01b5f52525ffd5b82604185634e487b7160e01b5f52525ffd5b8234610292575f366003190112610292575f5490516001600160a01b039091168152602090f35b34610292575f366003190112610292577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b67ffffffffffffffff811161038e57604052565b634e487b7160e01b5f52604160045260245ffd5b908060209392818452848401375f828201840152601f01601f191601019056fe60806040526102c8803803806100148161018e565b92833981019060408183031261018a5780516001600160a01b03811680820361018a5760208381015190936001600160401b03821161018a570184601f8201121561018a5780519061006d610068836101c7565b61018e565b9582875285838301011161018a5784905f5b8381106101765750505f9186010152813b1561015e577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b03191682179055604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a283511561014057505f80848461012796519101845af4903d15610137573d610118610068826101c7565b9081525f81943d92013e6101e2565b505b604051608290816102468239f35b606092506101e2565b925050503461014f5750610129565b63b398979f60e01b8152600490fd5b60249060405190634c9c8ce360e01b82526004820152fd5b81810183015188820184015286920161007f565b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176101b357604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116101b357601f01601f191660200190565b9061020957508051156101f757805190602001fd5b604051630a12f52160e11b8152600490fd5b8151158061023c575b61021a575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561021256fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e156048573d5ff35b3d5ffdfea2646970667358221220590de6162af1aca5f7d380e459394ce97dc6a2e4a2575dd7c58d5d1cb01c826d64736f6c6343000816003360a03461007157601f61025e38819003918201601f19168301916001600160401b038311848410176100755780849260209460405283398101031261007157516001600160a01b03811690819003610071576080526040516101d4908161008a82396080518181816073015260ca0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610044575b3615610018575f80fd5b7f7cb3607a76b32d6d17ca5d1aeb444650b19ac0fabbb1f24c93a0da57346b56106020604051348152a1005b5f3560e01c80634641257d146100a65763fbfa77cf0361000e57346100a2575f3660031901126100a2576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b346100a2575f3660031901126100a25760206100c06100c8565b604051908152f35b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361018c5747908115610187577f8e55ccfc9778ff8eba1646d765cf1982537ce0f9257054a17b48aad7452501836020604051848152a1333b156100a257604051630a62ade560e31b81525f8160048186335af1801561017c576101545750565b67ffffffffffffffff811161016857604052565b634e487b7160e01b5f52604160045260245ffd5b6040513d5f823e3d90fd5b5f9150565b604051630d599dd960e11b8152600490fdfea2646970667358221220d2fa2cef3e62e469cf54aa35037e52bcabbf6b0440b87e84467703a996c8184a64736f6c63430008160033a2646970667358221220e3e377542957101cf8fa4e50256e060c792a7e3641fc0e9eb2552a4c5b1a6fd164736f6c6343000816003300000000000000000000000035dc754f157b32ba0941ffcd89d16d3d0b2ca6cf0000000000000000000000003a0008a588772446f6e656133c2d5029cc4fc20e
Deployed Bytecode
0x6080604081815260049182361015610015575f80fd5b5f925f3560e01c9182635c60da1b14610339575081636f4fa30f146103125781639a0d79ad14610079575063e7f6f2251461004e575f80fd5b3461007557816003193601126100755760015490516001600160a01b039091168152602090f35b5080fd5b918091506003193601126102925781359267ffffffffffffffff928385116102925736602386011215610292578481013594848611610292576024928382019184883692010111610292578335928315158403610292578551946102c895868101968188108a891117610300576103c3823960608160018060a01b0398897f00000000000000000000000035dc754f157b32ba0941ffcd89d16d3d0b2ca6cf1681528a60208201525f8b8201520301905ff080156102e45786869116985f96610296575b506bffffffffffffffffffffffff60a01b9033826001541617600155893b15610292576101885f878c8e8d5180958194829363439fab9160e01b845260208d8501528b8401916103a2565b039134905af1801561028857610275575b5061026a575b60015416600155857f0000000000000000000000003a0008a588772446f6e656133c2d5029cc4fc20e1691823b156102665783918991838a5195869485936312b5ad0160e11b85528401525af1801561025c57610245575b505084926020969261023c7f0d606510f33b5e566ed1ca2b9e88d388ab81cea532909665d725b33134516aff938751938493168352878a8401523395888401916103a2565b0390a351908152f35b61024f829161037a565b61025957806101f7565b80fd5b86513d84823e3d90fd5b8380fd5b80845416845561019f565b61028091955061037a565b5f935f610199565b8a513d5f823e3d90fd5b5f80fd5b885191965061025e808301918211838310176102ee57602091839161068b83398b81520301905ff080156102e457861694856bffffffffffffffffffffffff60a01b5f5416175f555f61013d565b87513d5f823e3d90fd5b83604186634e487b7160e01b5f52525ffd5b82604185634e487b7160e01b5f52525ffd5b8234610292575f366003190112610292575f5490516001600160a01b039091168152602090f35b34610292575f366003190112610292577f00000000000000000000000035dc754f157b32ba0941ffcd89d16d3d0b2ca6cf6001600160a01b03168152602090f35b67ffffffffffffffff811161038e57604052565b634e487b7160e01b5f52604160045260245ffd5b908060209392818452848401375f828201840152601f01601f191601019056fe60806040526102c8803803806100148161018e565b92833981019060408183031261018a5780516001600160a01b03811680820361018a5760208381015190936001600160401b03821161018a570184601f8201121561018a5780519061006d610068836101c7565b61018e565b9582875285838301011161018a5784905f5b8381106101765750505f9186010152813b1561015e577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b03191682179055604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a283511561014057505f80848461012796519101845af4903d15610137573d610118610068826101c7565b9081525f81943d92013e6101e2565b505b604051608290816102468239f35b606092506101e2565b925050503461014f5750610129565b63b398979f60e01b8152600490fd5b60249060405190634c9c8ce360e01b82526004820152fd5b81810183015188820184015286920161007f565b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176101b357604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116101b357601f01601f191660200190565b9061020957508051156101f757805190602001fd5b604051630a12f52160e11b8152600490fd5b8151158061023c575b61021a575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561021256fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e156048573d5ff35b3d5ffdfea2646970667358221220590de6162af1aca5f7d380e459394ce97dc6a2e4a2575dd7c58d5d1cb01c826d64736f6c6343000816003360a03461007157601f61025e38819003918201601f19168301916001600160401b038311848410176100755780849260209460405283398101031261007157516001600160a01b03811690819003610071576080526040516101d4908161008a82396080518181816073015260ca0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610044575b3615610018575f80fd5b7f7cb3607a76b32d6d17ca5d1aeb444650b19ac0fabbb1f24c93a0da57346b56106020604051348152a1005b5f3560e01c80634641257d146100a65763fbfa77cf0361000e57346100a2575f3660031901126100a2576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b346100a2575f3660031901126100a25760206100c06100c8565b604051908152f35b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361018c5747908115610187577f8e55ccfc9778ff8eba1646d765cf1982537ce0f9257054a17b48aad7452501836020604051848152a1333b156100a257604051630a62ade560e31b81525f8160048186335af1801561017c576101545750565b67ffffffffffffffff811161016857604052565b634e487b7160e01b5f52604160045260245ffd5b6040513d5f823e3d90fd5b5f9150565b604051630d599dd960e11b8152600490fdfea2646970667358221220d2fa2cef3e62e469cf54aa35037e52bcabbf6b0440b87e84467703a996c8184a64736f6c63430008160033a2646970667358221220e3e377542957101cf8fa4e50256e060c792a7e3641fc0e9eb2552a4c5b1a6fd164736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000035dc754f157b32ba0941ffcd89d16d3d0b2ca6cf0000000000000000000000003a0008a588772446f6e656133c2d5029cc4fc20e
-----Decoded View---------------
Arg [0] : _implementation (address): 0x35dC754f157b32Ba0941ffCD89d16d3D0B2cA6CF
Arg [1] : vaultsRegistry (address): 0x3a0008a588772446f6e656133C2D5029CC4FC20E
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000035dc754f157b32ba0941ffcd89d16d3d0b2ca6cf
Arg [1] : 0000000000000000000000003a0008a588772446f6e656133c2d5029cc4fc20e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.