diff --git a/run-on-lido/stvaults-legacy/building-guides/basic-stvault.md b/run-on-lido/stvaults-legacy/building-guides/basic-stvault.md deleted file mode 100644 index 86eff3142..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/basic-stvault.md +++ /dev/null @@ -1,488 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 🧱 Basic stVault with optional liquidity - -## Intro - -This guide is aimed at helping Node Operators, Builders, Protocols, and Liquidity Providers create and operate an stVault with optional liquidity. - -### Product value proposition - -Competitive offering to native staking — users stake with the same Node Operator and get optional liquidity through stETH. - -### The vault strategy - -ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. - -## Environments - -### Testnet - -- UI: https://stvaults-hoodi.testnet.fi/ -- CLI: https://lidofinance.github.io/lido-staking-vault-cli/get-started/configuration -- Contracts: [Hoodi Testnet](/deployed-contracts/hoodi) -- Etherscan: https://hoodi.etherscan.io/ - -### Mainnet - -- UI: https://stvaults.lido.fi/ (will be available on [Phase 2 of the Rollout plan](https://research.lido.fi/t/lido-v3-design-implementation-proposal/10665/8)) -- CLI: https://lidofinance.github.io/lido-staking-vault-cli/get-started/configuration -- Contracts: [Mainnet](/deployed-contracts) -- Etherscan: https://etherscan.io/ - -## Steps - -### Create an stVault - -Creating an stVault is permissionless. There are two main ways to do it: - -1. Two-step process (recommended): initiated by the Node Operator and completed by the Vault Owner. -2. One-step process (for experienced Vault Owners / Stakers): create the stVault and supply 1 ETH in a single transaction. - -#### Parameters needed to create an stVault: - -1. **Node Operator address** — a unique, immutable identifier of the Node Operator within stVaults, used in protocol logic such as calculating per-operator stETH minting terms and limits. It designates the Node Operator that provides validation services for the stVault and also manages ETH deposits from the stVault balance to validators, as well as handling validator exits when required. -2. **Node Operator Manager address**. One of the two administrative roles in an stVault. From the Node Operator perspective, this role manages permissions and can update key vault parameters. Multiple addresses are supported. -3. **Vault Owner address**. One of the two administrative roles in an stVault. From the Vault Owner (Staker) perspective, this role manages permissions and can update key vault parameters. Multiple addresses are supported. -4. **Node Operator Fee**. The share of gross staking rewards that the Node Operator charges for providing validation services. Expressed in basis points [0 (0%) .. 10,000 (100%)]. -5. **Confirmation Lifetime**. The key parameter of the multi-role confirmation mechanism. It defines the maximum time interval between proposal and confirmation. This mechanism is used to update certain stVault parameters by requiring consensus between the two stVault representatives: the Vault Owner and the Node Operator Manager. Measured in seconds [86,400 sec (24 hours) .. 2,592,000 sec (30 days)]. For security reasons, it is strongly recommended to keep it as short as possible, ideally the minimum 86,400 sec. - -#### 1. Two-step process (recommended) - -This approach enables a Node Operator to create an stVault without providing their own ETH. It is recommended because it prevents ETH commingling and streamlines the experience for Stakers and Vault Owners. - -##### 1.1. **Node Operator** creates an stVault that is not yet connected to Lido Core. - -Creating an stVault is a permissionless operation, but in this two-step process it is usually performed by the Node Operator. - -
- by Command-line Interface - ```bash - yarn start vo w create-vault create-without-connecting --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 - ``` - Note down the addresses of the created **Vault** and **Dashboard** contracts — these are the key contracts of your newly created stVault. -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **VaultFactory** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Go to the **Contract** tab → **Write Contract**. - 3. Click **Connect to Web3** and connect your wallet in the dialog window. - 4. Find the method `createVaultWithDashboardWithoutConnectingToVaultHub` in the list, fill out the fields, and click **Write**. - - You can leave `_roleAssignments = []`. - 5. Sign the transaction in your wallet. - 6. Click **View your transaction** and wait for it to be executed. - 7. Open the **Logs** tab, scroll to the **DashboardCreated** event, and note down the addresses of the created **Vault** and **Dashboard** contracts — these are the key contracts of your newly created stVault. -
- -##### 1.2. When an stVault is created, the Node Operator may optionally propose a tier with more favorable stETH minting terms than the Default tier. - -To perform this step, the Node Operator of the newly created vault must already have individual tiers assigned. Otherwise, the stVault will remain limited to the Default tier option `(tierID = 0)`. - -**Parameters needed for this step:** - -- `VaultAddress`: the address of the `Vault` contract. -- `TierID`: the ID of the tier to which the stVault will be connected. -- `RequestedShareLimit`: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier’s stETH limit. [Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). - -
- by Command-line Interface - ```bash - yarn start contracts operator-grid w ct - ``` -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **Operator Grid** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the `changeTier` method in the list, fill out the fields, and click **Write**. - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. -
- -##### 1.3. After that, the **Vault Owner**, in one transaction, accepts the stETH minting parameters and fees (by accepting the tier), supplies 1 ETH as collateral for connection to Lido Core, and initiates the connection to Lido Core. - -This is a permissioned operation. By default, this permission belongs to the Vault Owner, who can delegate it to other addresses (multiple supported, including the Vault Owner’s own address). [Read more about roles](../features-and-mechanics/roles-and-permissions). - -**Parameters and addresses needed for this step:** - -- `VaultAddress`: the address of the `Vault` contract. -- `TierID`: the ID of the tier to which the stVault will be connected. -- `RequestedShareLimit`: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier’s stETH limit. [Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). -- `payableAmount`: the amount of ETH to supply in the same transaction; minimum is **1 ETH**. -- `currentSettledGrowth`: the amount of unaccounted growth accrued on the vault while it was disconnected; 0 for newly created vaults via the create-without-connecting method. Settled growth is the part of the total growth that has already been charged by the node operator or is not subject to fee (exempted), such as unguaranteed or side deposits, and consolidations accrued while the vault was disconnected. - -
- using stVaults Web UI - 1. Open the stVaults mainpage (see [#Environments](#environments)) - - 2. Connect wallet on the "My Vaults" page. - - 3. Open an stVault overview page at `https:///vaults/` - - ![Connect and accept tier](/img/stvaults/guide-basic-stvault/guide_1_scr_8.png) - - 4. Review parameters and click "Approve and supply 1 ETH". - - 5. Sign transaction in the wallet. - -
-
- by Command-line Interface - ```bash - yarn start contracts dashboard w connect-and-accept-tier -f - ``` -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **Dashboard** contract by its address (provided in the results of stVault creation, see step 1.1). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the `connectAndAcceptTier` method in the list, fill out the fields, and click **Write**. - - fill out the `payableAmount` field with '1' to supply `1 ETH` in the same transaction. - - set the `_currentSettledGrowth` field to '0' for a newly created vault like in this scenario (if the stVault is newly created but had side deposits before connecting, settled growth must be set accordingly before the connection). - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. -
- -#### 2. One-step process (for experienced Vault Owners / Stakers) - -In this approach, the Vault Owner creates an stVault that automatically connects to Lido Core, enabling stETH minting. This requires supplying 1 ETH, which will be locked as collateral for the connection to Lido Core. All completed in a single transaction, so despite being a permissionless operation, it is usually performed by the Vault Owner of the future stVault. - -
- using stVaults Web UI - 1. Open the stVaults mainpage (see [#Environments](#environments)) - 2. Connect wallet on the "My Vaults" page. - 3. Click "Create vault". - - ![Create vault](/img/stvaults/guide-basic-stvault/guide_1_scr_9.png) - - 4. Fill out the form and click "Continue". - 5. Sign transaction in the wallet. - -
-
- by Command-line Interface - ```bash - yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 - ``` -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **VaultFactory** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Go to the **Contract** tab → **Write Contract**. - 3. Click **Connect to Web3** and connect your wallet in the dialog window. - 4. Find the method `createVaultWithDashboard` in the list, fill out the fields, and click **Write**. - - `_payableAmount (ether)` must be at least **1 ETH**. - - You can leave `_roleAssignments = []`. - 5. Sign the transaction in your wallet. - 6. Click **View your transaction** and wait for it to be executed. - 7. Open the **Logs** tab, scroll to the **DashboardCreated** event, and note down the addresses of the created **Vault** and **Dashboard** contracts — these are the key contracts of your newly created stVault. -
- -### Adjust stETH minting parameters - -By default, a newly created stVault is connected to the Default tier with a Reserve Ratio of 50%. If the Node Operator has passed identification and been granted individual tiers, the stVault can be moved from the Default tier to one of the Node Operator’s tiers to access better stETH minting conditions. - -When using vault creation method #1 ("Two-step process"), the Node Operator and Vault Owner can set up the stVault with the desired stETH minting parameters from the start. Otherwise, the tier can be changed afterwards. - -Tier changes are performed via a multi-role confirmation mechanism, where the Node Operator and Vault Owner act as contracting parties. One party proposes the change, and the other party accepts it. Technically, both requests are made through the same method: `changeTier(tierId, requestedShareLimit)`. - -Both parties must submit the request with identical parameters within the confirmation lifetime of 24 hours for the change to take effect. - -Addresses performing this operation must have the following roles ([Read more about roles](../features-and-mechanics/roles-and-permissions)): - -- From the Vault Owner: Vault Owner (Admin DEFAULT_ADMIN_ROLE, or delegated VAULT_CONFIGURATION_ROLE). -- From the Node Operator: Node Operator (registered in the `OperatorGrid` contract). - -Confirming tier change request requires applying fresh report to vault. [Read more about applying reports](../operational-and-management-guides/applying-report-guide) - -**Parameters and addresses needed for this step (for CLI and Smart contracts):** - -- `VaultAddress`: the address of the `Vault` contract. -- `TierID`: the ID of the tier to which the stVault will be connected. -- `RequestedShareLimit`: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier’s stETH limit. [Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). - -
- using stVaults Web UI - 1. On behalf of the first contracting party, open 'Settings > Tiers', and click the tier selector: - - ![Settings > Tiers](/img/stvaults/guide-basic-stvault/guide_1_scr_1.png) - - 2. Select the desired tier from the list: - - ![Selecting Tier](/img/stvaults/guide-basic-stvault/guide_1_scr_2.png) - - 3. Review how the stVault metrics will change after moving to the new tier, then submit your request/proposal. - - ![Review settings](/img/stvaults/guide-basic-stvault/guide_1_scr_3.png) - - 4. On behalf of the other contracting party, open 'Settings > Tiers'. - - ![Open proposal](/img/stvaults/guide-basic-stvault/guide_1_scr_4.png) - - 5. Open the request details, review the projected changes to the stVault metrics, and submit approval. - - ![Review settings](/img/stvaults/guide-basic-stvault/guide_1_scr_5.png) - -
- -
- by Command-line Interface - - On behalf of the Vault Owner ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations/#change-tier-ct)): - - ```bash - yarn start vo w change-tier -v -r - ``` - - On behalf of the Node Operator ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations/#change-tier-by-no-ct-no)): - - ```bash - yarn start vo w change-tier-by-no -v -r - ``` - -
-
- using Etherscan UI - - The Node Operator and Vault Owner use same-named methods in different contracts to perform this change. - - **Node Operator:** - 1. Open **Etherscan** and navigate to the **Operator Grid** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the `changeTier` method in the list, fill out the fields, and click **Write**. - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. - - **Vault Owner:** - 1. Open **Etherscan** and navigate to the **Dashboard** contract by its address (provided in the results of stVault creation, see step 1.1). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the `changeTier` method in the list, fill out the fields, and click **Write**. - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. - -
- -### Supply and withdraw ETH - -Supply and Withdraw ETH are permissioned operations. By default, these permissions belong to the Vault Owner, who can delegate them to other addresses (multiple are supported, including the Vault Owner’s own address). [Read more about roles](../features-and-mechanics/roles-and-permissions). - -Before withdrawing ETH or performing other operations that depend on current vault state, ensure that a fresh report for your vault is applied. [Read more about applying reports](../operational-and-management-guides/applying-report-guide) - -Withdrawable ETH is defined by ([Read more about stVaults metrics](../features-and-mechanics/parameters-and-metrics)): - -- stVault Balance - ETH that is not staked on validators. -- Total lock — collateral reserved for stETH liability, the mandatory 1 ETH minimal reserve for connecting the stVault to Lido Core, and protocol and Node Operator fee obligations. - -
- using stVaults Web UI - - Supply / Withdraw section: - ![Supply and Withdraw](/img/stvaults/guide-basic-stvault/guide_1_scr_6.png) - When supplying, you can mint all amount of available stETH immediately by selecting the checkbox. - When withdrawing, you can specify a destination address for the withdrawal. You can also choose which token to supply or withdraw: ETH or wETH. - -
-
- by Command-line Interface - -Supply (fund) ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/get-started/supply-withdrawal#fund-vault)): - -```bash -yarn start vo w fund -``` - -Withdraw ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/get-started/supply-withdrawal#withdraw-from-vault)): - -```bash -yarn start vo w withdraw -``` - -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **Dashboard** contract by its address (provided in the results of stVault creation, see step 1.1). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the required method in the list, fill out the fields, and click **Write**: - - `fund` to supply (fund) ETH into the stVault. - - `withdraw` to withdraw ETH from the stVault balance (accepts wei for amount). - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. -
- -### Mint and repay stETH - -When ETH is supplied to an stVault, the Vault Owner can mint stETH on demand. -Unlike Lido Core, stVaults allow stETH minting only within the defined [stETH minting capacity](../features-and-mechanics/parameters-and-metrics#total-steth-minting-capacity). - -Mint and Repay stETH are permissioned operations. By default, these permissions belong to the Vault Owner, who can delegate them to other addresses (multiple supported, including the Vault Owner’s own address). [Read more about roles](../features-and-mechanics/roles-and-permissions). - -Before minting stETH or performing other operations that depend on current vault state, ensure that a fresh report for your vault is applied. [Read more about applying reports](../operational-and-management-guides/applying-report-guide) - -After stETH is repaid, the corresponding ETH is unlocked once the upcoming Oracle report confirms the repaid amount. - -
- using stVaults Web UI - - Mint / Repay section: - ![Mint and Repay](/img/stvaults/guide-basic-stvault/guide_1_scr_7.png) - When minting stETH, you can specify an address to receive it. You can also choose which token to mint or repay: stETH or wstETH. - -
-
- by Command-line Interface - -Mint ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/get-started/mint-burn#mint-operations)): - -- Mint Shares `yarn start vo w mint-shares ` -- Mint stETH tokens (rebasing): `yarn start vo w mint-steth ` -- Mint wrapped stETH tokens (non-rebasing): `yarn start vo w mint-wsteth ` - -Repay (burn) ([details and examples](https://lidofinance.github.io/lido-staking-vault-cli/get-started/mint-burn#burn-operations)): - -- Repay (burn) vault shares: `yarn start vo w burn ` -- Repay (burn) stETH tokens: `yarn start vo w burn-steth ` -- Repay (burn) wrapped stETH tokens: `yarn start vo w burn-wsteth ` - -[Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). - -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **Dashboard** contract by its address (provided in the results of stVault creation, see step 1.1). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Write as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the required method in the list, fill out the fields, and click **Write**: - - `mintShares` to mint shares; - - `mintStETH` to mint stETH token (rebasing); - - `mintWstETH` to mint the wrapped token wstETH (non-rebasing); - - `burnShares` to repay (burn) shares; - - `burnStETH` to repay (burn) stETH token; - - `burnWstETH` to repay (burn) the wrapped token wstETH; - 6. Sign the transaction in your wallet. - 7. Click **View your transaction** and wait for it to be executed. - - To repay (burn) shares, stETH or wstETH you must first grant approval to the vault's Dashboard contract. Go to the stETH or wstETH token contract and execute the `approve()` method for the amount (in wei) you want to set as allowance. Only after the approval is confirmed you can proceed with the repay (burn) operation. Please also note that if you are trying to mint shares (instead of stETH or wstETH), in that case you may need to approve slightly different amount of stETH then you are trying to mint. Please find the contracts' addresses on the **Contracts** page in accordance with your [environment](#environments). - -[Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). - -
- -### Deposit ETH to validators - -Supplying ETH to the stVault increases its balance. The Node Operator can then deposit ETH from this balance into validators. - -**The Predeposit Guarantee (PDG)** contract, as part of the stVaults platform, helps prevent deposit frontrunning caused by the vulnerabilities described in [LIP-5](https://research.lido.fi/t/lip-5-mitigations-for-deposit-front-running-vulnerability/1269). PDG secures the Vault Owner’s ETH deposits to validators from being front-run by the Node Operator. - -One of the key benefits of using PDG is the avoidance of commingling: it keeps the finances of the Vault Owner and the Node Operator strictly separated. - -PDG enables three main use cases: - -- **Full-cycle proof of validators.** Enables a non-custodial deposit mechanism by using guarantee ETH as collateral. [Follow the main guide](../tech-documentation/pdg#full-cycle-trustless-path-through-pdg). -- **PDG shortcut.** Allows skipping the pre-deposit steps and depositing directly to a validator without using PDG initially. The validator can later be associated with the vault by proving it through PDG. This path is applicable when there is unconditional trust between the Node Operator and the Vault Owner. [Follow the shortcut guide](../tech-documentation/pdg#pdg-shortcut). -- **Adding existing validators.** Lets you connect an existing validator from external staking infrastructure to an stVault as an advanced integration use case. [Consolidations guide](../tech-documentation/consolidation) - -Read more: [Technical details](https://hackmd.io/@lido/stVaults-design#315-Essentials-PredepositGuarantee); [GitHub Repository](https://github.com/lidofinance/core/blob/feat/vaults/contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol). - -### Monitor stVault health and rebalance - -The key stVault metrics that the Vault Owner should monitor and control are: - -- **Utilization ratio** — the share of the stETH minting capacity currently used by the Vault Owner. [Learn more](../features-and-mechanics/parameters-and-metrics) -- **Health Factor** — a metric that reflects the economic state of the vault. It shows how the stETH liability is collateralized by the Total Value. A Health Factor of 100% corresponds to the Forced Rebalance Threshold, meaning that if the Health Factor falls below 100%, the stVault becomes subject to forced rebalancing. [Learn more](../features-and-mechanics/parameters-and-metrics) - -Read more: - -- [Health Monitoring Guide](../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../operational-and-management-guides/health-emergency-guide.md) - -The Health Factor metric may decrease as a result of validator underperformance, penalties, or a slashing event. - -If this happens, there are three main options available: - -- Supply ETH to increase Total Value. -- Repay stETH to reduce stETH liability. -- Rebalance ETH (optionally combined with a supply in a single transaction). - -**Rebalancing** involves transferring available ETH from the stVault balance to Lido Core, receiving stETH at a 1:1 ratio, and repaying it back to the stVault. This reduces stETH liability and thereby increases the Health Factor. - -Rebalancing is performed in one transaction. - -The amount of ETH required for rebalancing to bring the Utilization Ratio to 100% depends on the current Health Factor and Reserve Ratio. It can be pre-calculated manually using the formula, or via the built-in methods. - -
- by Formula - - ETH for rebalance = (stETH Liability − (1 − Reserve Ratio) × Total Value) / Reserve Ratio - -
-
- by Command-line Interface - - See the [CLI documentation](https://lidofinance.github.io/lido-staking-vault-cli/) for rebalance commands. - -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **VaultHub** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Read as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the method `healthShortfallShares` in the list, fill out the input with the `vault` contract address, and click **Query**. - 6. Receive the result right under the submit button. -
- -## Useful links - -- [stVaults Roles](../features-and-mechanics/roles-and-permissions) -- [stVaults Metrics](../features-and-mechanics/parameters-and-metrics) -- [Health Monitoring Guide](../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../operational-and-management-guides/health-emergency-guide.md) -- [Applying Oracle Reports](../operational-and-management-guides/applying-report-guide) diff --git a/run-on-lido/stvaults-legacy/building-guides/index.md b/run-on-lido/stvaults-legacy/building-guides/index.md deleted file mode 100644 index 71db7e28c..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 🛠️ Building Guides - -The stVaults platform enables the creation of staking products tailored to different target audiences with diverse needs. These two comprehensive guides provide detailed instructions on how to create any product powered by stVaults. - -| Staking Product to build | Its Value Proposition | Its Segments | -|-----------------------------------------------------------------------| -------- | -------- | -| [Basic stVault with optional liquidity](./basic-stvault.md) | A competitive alternative to native staking: users stake with the same Node Operator while gaining optional liquidity through stETH. | Institutional stakers, large individual stakers (32+ ETH), funds, treasuries, builders, integrators, liquidity providers. | -| [End-user staking product by DeFi Wrapper](./pooled-staking-product/) | A DeFi-wrapped stVault with pooling, liquidity, automated yield-boosting strategy, and white-labeled staking UI – all in one customizable no-code/low-code solution. | Retail stakers (<32 ETH), APR-maximizers, institutional stakers seeking a simple staking UI. | - -:::info -Have your own custom product in mind? [Contact us](https://tally.so/r/mVrkZa)! -::: diff --git a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/custom-strategy.md b/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/custom-strategy.md deleted file mode 100644 index 474935d5e..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/custom-strategy.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -sidebar_position: 4 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# 🧩 Pool with a custom strategy - -## Intro - -This guide walks through how to build and deploy a **pooled staking product with a custom yield strategy** using the DeFi Wrapper toolkit. - -The DeFi Wrapper architecture is designed to support **any custom strategy** as long as it implements the required interfaces. - -There are **two paths** to getting a pool with a custom strategy: - -1. [**Deploy from scratch**](#path-a-deploy-a-new-pool-with-custom-strategy) - Already have a custom strategy and ready to launch a pool - -2. [**Upgrade existing pool**](#path-b-upgrade-an-existing-pool-to-a-strategy-pool) - Create a pool and add a custom strategy later - -Both paths share the same smart-contract development steps (implementing `IStrategy` and `IStrategyFactory`). - -## Smart contract development - -1. Implement the [`IStrategy`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/interfaces/IStrategy.sol) interface - -2. Implement the [`IStrategyFactory`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/interfaces/IStrategyFactory.sol) interface. - The `_deployBytes` parameter can be used to pass additional strategy-specific configuration during deployment. If your strategy doesn't need extra config, it can be ignored. - -3. Deploy the strategy factory - -:::note -Note the deployed **strategy factory address** — you will need it in Path A. -::: - -:::warning -Make sure to deploy the strategy factory on the same network where you will create the pool (Hoodi testnet for testing, Ethereum mainnet for production). -::: - ---- - -## Path A: Deploy a new pool with custom strategy - -Use this path when launching a new product from scratch. - -### Create the pool via CLI - -Use the `create-pool-custom` command to deploy the pool with your strategy: - -```bash -yarn start defi-wrapper contracts factory w create-pool-custom \ - --nodeOperator \ - --nodeOperatorManager \ - --nodeOperatorFeeRateBP 10 \ - --confirmExpiry 86400 \ - --minDelaySeconds 3600 \ - --minWithdrawalDelayTime 3600 \ - --name "My Custom Strategy Pool" \ - --symbol STV \ - --proposer \ - --executor \ - --emergencyCommittee \ - --reserveRatioGapBP 250 \ - --mintingEnabled true \ - --allowList true \ - --allowListManager \ - --strategyFactory \ - --strategyFactoryDeployBytes -``` - -Run `yarn start defi-wrapper contracts factory write create-pool-custom -h` for the full description of all available parameters. - -:::info -The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the vault upon connection to Lido `VaultHub`. -::: - -
- Parameter reference - -| Parameter | Description | -|-----------|-------------| -| `` | DeFi Wrapper Factory contract address (see [Environments](/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/#environments)) | -| `--nodeOperator` | Address of the Node Operator managing validators | -| `--nodeOperatorManager` | Address authorized to manage Node Operator settings | -| `--nodeOperatorFeeRateBP` | Node Operator fee in basis points (10 = 0.1%) | -| `--confirmExpiry` | Confirmation timeout in seconds | -| `--minDelaySeconds` | TimeLock minimum delay before execution | -| `--minWithdrawalDelayTime` | Minimum delay before withdrawals can be finalized | -| `--name` | ERC-20 pool share token name | -| `--symbol` | ERC-20 pool share token symbol | -| `--proposer` | Address authorized to propose TimeLock operations | -| `--executor` | Address authorized to execute TimeLock operations | -| `--emergencyCommittee` | Address that can pause pool operations | -| `--reserveRatioGapBP` | Reserve ratio gap in basis points (recommended min: 250) | -| `--mintingEnabled` | Enable stETH minting (`true` / `false`) | -| `--allowList` | Enable deposit allowlist (`true` / `false`) | -| `--allowListManager` | Address managing the allowlist | -| `--strategyFactory` | Your deployed strategy factory address | -| `--strategyFactoryDeployBytes` | Optional hex-encoded bytes passed to your factory's `deploy()` | - -
- -:::warning -The minimum recommended value for `reserveRatioGapBP` is `250` (2.5%). It is expected to be sufficient to absorb enough of the vault's performance volatility to keep users' positions healthy in most cases. -::: - - -After successful deployment, the CLI outputs the addresses and environment variables you need: - -- **Vault** contract address -- **Pool** contract address -- **WithdrawalQueue** contract address -- **Distributor** contract address -- **Strategy** contract address -- **TimeLock** contract address -- UI environment variables (`VITE_POOL_ADDRESS`, `VITE_POOL_TYPE`, etc.) - -:::info -Keep the CLI output — you will need these addresses for the UI setup and ongoing operations. -::: - -Continue with [Post-deployment steps](/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/#2-create-web-ui). - ---- - -## Path B: Upgrade an existing pool to a strategy pool - -Use this path when you have a running [`StvStETHPool`](/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/#deployment-of-stvstethpool-pool-with-steth-minting) and want to add a strategy without redeploying the pool. All existing user balances and state are preserved through the proxy upgrade. - -:::info -This upgrade path uses the [`OssifiableProxy`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/proxy/OssifiableProxy.sol) pattern. The pool contract is a proxy whose implementation can be swapped by its admin (the `TimelockController`). Storage (user balances, roles, parameters) lives in the proxy and is preserved across implementation changes. -::: - -### What changes during the upgrade - -| Aspect | Before (`StvStETHPool`) | After (`StvStrategyPool`) | -|--------|------------------------|--------------------------------------| -| Pool type | `STV_STETH_POOL_TYPE` | `STRATEGY_POOL_TYPE` | -| Allowlist | Disabled | Enabled (only strategy can deposit) | -| Strategy | None | Your custom strategy contract | -| Direct user deposits | Allowed | Blocked (users go through strategy) | -| User STV balances | ✅ Preserved | ✅ Preserved | -| Vault, Dashboard, WQ | ✅ Unchanged | ✅ Unchanged | - -### Deploy the new pool implementation and strategy - -You need two new contracts: a new pool implementation (with `STRATEGY_POOL_TYPE` and `allowListEnabled = true`) and the strategy itself. - -#### Deploy new pool implementation - -Use the existing `StvStETHPoolFactory` to create a new implementation with the correct pool type: - -```bash -cast send \ - "deploy(address,bool,uint256,address,address,bytes32)(address)" \ - \ - true \ - \ - \ - \ - \ - --rpc-url $RPC_URL \ - --private-key $DEPLOYER_KEY -``` - -Parameters: -- `` — the `StvStETHPoolFactory` address from the DeFi Wrapper Factory (`Factory.STV_STETH_POOL_FACTORY()`) -- `` — your pool's existing Dashboard address -- `true` — enables the allowlist (immutable in the new implementation) -- `` — same value as the existing pool (e.g., `500`) -- `` — your pool's existing WithdrawalQueue address -- `` — your pool's existing Distributor address -- `` — the strategy pool type hash (`Factory.STRATEGY_POOL_TYPE()`) - -Note the deployed **new pool implementation address**. - -#### Deploy strategy implementation - -Deploy the strategy implementation contract. For example: - -```bash -forge create src/strategy/MyStrategy.sol:MyStrategy \ - --rpc-url $RPC_URL \ - --private-key $DEPLOYER_KEY \ - --broadcast \ - --constructor-args -``` - -Note the deployed **strategy implementation address**. - -#### Deploy strategy proxy - -The strategy must be deployed behind an [`OssifiableProxy`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/proxy/OssifiableProxy.sol). The proxy is created with three parameters: - -- `implementation_` — the strategy implementation address from the previous step -- `admin_` — the pool's `TimelockController` address (proxy admin who can upgrade the implementation) -- `data_` — the ABI-encoded `initialize` calldata to be executed on the implementation during proxy creation - -First, encode the `initialize` calldata: - -```bash -INITIALIZE_CALLDATA=$(cast calldata "initialize(address,address)" ) -``` - -Where: -- `` — the pool's TimelockController address (will receive `DEFAULT_ADMIN_ROLE` on the strategy) -- `` — address that will receive the initial pause role (e.g., `SUPPLY_PAUSE_ROLE`) - -Then deploy the proxy: - -```bash -forge create src/proxy/OssifiableProxy.sol:OssifiableProxy \ - --rpc-url $RPC_URL \ - --private-key $DEPLOYER_KEY \ - --broadcast \ - --constructor-args $INITIALIZE_CALLDATA -``` - -Note the deployed **strategy proxy address** — this is the address you will use in the TimelockController batch below. - -:::warning -The proxy admin must be the pool's `TimelockController` address. The `initialize` call sets the Timelock as the strategy's `DEFAULT_ADMIN_ROLE` holder. -::: - -### Execute the upgrade via TimelockController batch - -The upgrade must be executed as an **atomic batch** through the `TimelockController` to prevent an intermediate state where the allowlist is enabled but the strategy is not yet allowlisted. - -The batch consists of operations, all targeting the pool proxy: - -:::warning -The exact number and content of operations depends on the current pool configuration (e.g., whether minting is paused, which roles are assigned). The example below is illustrative and may differ in your case. -::: - -| # | Operation | Purpose | -|---|-----------|---------| -| 1 | `proxy__upgradeToAndCall(newImpl, "")` | Swap implementation to strategy pool type | -| 2 | `grantRole(ALLOW_LIST_MANAGER_ROLE, timelock)` | Temporarily grant allowlist management to Timelock | -| 3 | `addToAllowList(strategyProxy)` | Allow the strategy to deposit into the pool | -| 4 | `revokeRole(ALLOW_LIST_MANAGER_ROLE, factory)` | Remove Factory's allowlist management | -| 5 | `revokeRole(ALLOW_LIST_MANAGER_ROLE, timelock)` | Remove Timelock's temporary allowlist management | -| 6 | `revokeRole(DEPOSITS_PAUSE_ROLE, nodeOperator)` | Adjust pause roles for the new setup | -| 7 | `revokeRole(MINTING_PAUSE_ROLE, nodeOperator)` | Adjust pause roles for the new setup | -| 8 | `grantRole(MINTING_RESUME_ROLE, timelock)` | Temporarily grant minting resume capability | -| 9 | `resumeMinting()` | Re-enable minting (needed if paused in the original pool) | -| 10 | `revokeRole(MINTING_RESUME_ROLE, timelock)` | Remove temporary minting resume capability | - -:::info -Steps 8–10 (resume minting) are only needed if minting was paused in the original pool. If minting was already active, these steps can be omitted from the batch. -::: - -:::info -Steps 6–7 (revoke pause roles from the Node Operator) adjust the emergency role setup to match the strategy pool configuration. Review the [DeFi Wrapper roles and permissions](./roles-and-permissions) to decide what role assignment is appropriate for your setup. -::: - -
- Step 1: Prepare calldata for each operation - -Use `cast` (from Foundry) to encode each payload: - -```bash -# 1. Upgrade pool implementation -PAYLOAD_1=$(cast calldata "proxy__upgradeToAndCall(address,bytes)" 0x) - -# 2. Grant ALLOW_LIST_MANAGER_ROLE to timelock -ALLOW_LIST_MANAGER_ROLE=$(cast call "ALLOW_LIST_MANAGER_ROLE()(bytes32)" --rpc-url $RPC_URL) -PAYLOAD_2=$(cast calldata "grantRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE ) - -# 3. Add strategy to allowlist -PAYLOAD_3=$(cast calldata "addToAllowList(address)" ) - -# 4. Revoke ALLOW_LIST_MANAGER_ROLE from factory -PAYLOAD_4=$(cast calldata "revokeRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE ) - -# 5. Revoke ALLOW_LIST_MANAGER_ROLE from timelock -PAYLOAD_5=$(cast calldata "revokeRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE ) - -# 6. Revoke DEPOSITS_PAUSE_ROLE from node operator -DEPOSITS_PAUSE_ROLE=$(cast call "DEPOSITS_PAUSE_ROLE()(bytes32)" --rpc-url $RPC_URL) -PAYLOAD_6=$(cast calldata "revokeRole(bytes32,address)" $DEPOSITS_PAUSE_ROLE ) - -# 7. Revoke MINTING_PAUSE_ROLE from node operator -MINTING_PAUSE_ROLE=$(cast call "MINTING_PAUSE_ROLE()(bytes32)" --rpc-url $RPC_URL) -PAYLOAD_7=$(cast calldata "revokeRole(bytes32,address)" $MINTING_PAUSE_ROLE ) - -# 8. Grant MINTING_RESUME_ROLE to timelock -MINTING_RESUME_ROLE=$(cast call "MINTING_RESUME_ROLE()(bytes32)" --rpc-url $RPC_URL) -PAYLOAD_8=$(cast calldata "grantRole(bytes32,address)" $MINTING_RESUME_ROLE ) - -# 9. Resume minting -PAYLOAD_9=$(cast calldata "resumeMinting()") - -# 10. Revoke MINTING_RESUME_ROLE from timelock -PAYLOAD_10=$(cast calldata "revokeRole(bytes32,address)" $MINTING_RESUME_ROLE ) -``` - -
- -
- Step 2: Schedule the batch (Proposer) - -Call `TimelockController.scheduleBatch` on the Timelock contract. This can be done via **Etherscan** or `cast`: - -```bash -POOL= -PREDECESSOR=0x0000000000000000000000000000000000000000000000000000000000000000 -SALT=0x0000000000000000000000000000000000000000000000000000000000000000 -DELAY= - -cast send \ - "scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)" \ - "[$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL]" \ - "[0,0,0,0,0,0,0,0,0,0]" \ - "[$PAYLOAD_1,$PAYLOAD_2,$PAYLOAD_3,$PAYLOAD_4,$PAYLOAD_5,$PAYLOAD_6,$PAYLOAD_7,$PAYLOAD_8,$PAYLOAD_9,$PAYLOAD_10]" \ - $PREDECESSOR \ - $SALT \ - $DELAY \ - --rpc-url $RPC_URL \ - --private-key $PROPOSER_KEY -``` - -Note the **operation ID** from the `CallScheduled` event in the transaction logs. - -
- -
- Step 3: Execute the batch (Executor) - -After the timelock delay has passed, execute the batch: - -```bash -cast send \ - "executeBatch(address[],uint256[],bytes[],bytes32,bytes32)" \ - "[$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL]" \ - "[0,0,0,0,0,0,0,0,0,0]" \ - "[$PAYLOAD_1,$PAYLOAD_2,$PAYLOAD_3,$PAYLOAD_4,$PAYLOAD_5,$PAYLOAD_6,$PAYLOAD_7,$PAYLOAD_8,$PAYLOAD_9,$PAYLOAD_10]" \ - $PREDECESSOR \ - $SALT \ - --rpc-url $RPC_URL \ - --private-key $EXECUTOR_KEY -``` - -You can verify the operation is ready before executing: -```bash -cast call "isOperationReady(bytes32)(bool)" --rpc-url $RPC_URL -``` - -
- -### Verify the upgrade via CLI - -```bash -yarn start defi-wrapper contracts pool r info -yarn start vo r info -v -``` - -### What users experience after the upgrade - -- **Existing STV balances** are fully preserved — users keep their tokens. -- **Direct deposits** to the pool are no longer possible (blocked by allowlist). Users must go through the strategy. -- **Existing STV holders** can approve and deposit their tokens into the strategy to start receiving strategy-boosted yield. -- **Withdrawals** of existing STV continue to work through the WithdrawalQueue as before. - ---- - -## Reference implementation - -The [`GGVStrategy`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/strategy/GGVStrategy.sol) and its [`GGVStrategyFactory`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/factories/GGVStrategyFactory.sol) serve as the reference implementation for custom strategies. - -Study them to understand the complete pattern, including: - -- How `StrategyCallForwarderRegistry` manages per-user proxies -- How `FeaturePausable` enables granular pause control -- How to handle ERC-20 approvals and transfers through call forwarders -- How to implement cancel/replace flows for pending exit requests -- How the proxy upgrade preserves all user state - -The [upgrade integration test](https://github.com/lidofinance/vaults-wrapper/blob/develop/test/integration/wrapper-upgrade-b-to-c.test.sol) demonstrates the complete `StvStETHPool` → strategy pool upgrade flow. - -## Useful links - -- [DeFi Wrapper Technical Design](https://hackmd.io/@lido/lido-v3-wrapper-design) -- [IStrategy interface](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/interfaces/IStrategy.sol) -- [IStrategyFactory interface](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/interfaces/IStrategyFactory.sol) -- [Upgrade integration test (StvStETHPool → strategy pool)](https://github.com/lidofinance/vaults-wrapper/blob/develop/test/integration/wrapper-upgrade-b-to-c.test.sol) -- [stVaults CLI documentation](https://lidofinance.github.io/lido-staking-vault-cli/) -- [stVaults Roles and Permissions](/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions) -- [Health Monitoring Guide](../../operational-and-management-guides/health-monitoring-guide.md) diff --git a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/disconnect-guide.md b/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/disconnect-guide.md deleted file mode 100644 index 7aeb043fa..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/disconnect-guide.md +++ /dev/null @@ -1,426 +0,0 @@ ---- -sidebar_position: 5 ---- - -# 🔌 DeFi Wrapper Disconnect Guide - -This guide walks through the full process of disconnecting a DeFi Wrapper (pooled staking product) from the Lido protocol and distributing remaining assets to users. - -:::warning -Disconnecting a DeFi Wrapper is an irreversible operation that affects all pool users. Ensure you communicate the timeline and plan to your users well in advance. -::: - -## Overview - -1. **Assign required roles** to a trusted actor via the Timelock Controller. -2. **Exit all validators** (voluntarily or forcibly). -3. **Pause withdrawals** on the Withdrawal Queue and **finalize all pending withdrawal requests**. -4. **Pause deposits and minting** on the Pool contract. -5. **Rebalance the Staking Vault** to zero liability. -6. **Disconnect the stVault** — follow the [stVault Disconnect Guide](../../operational-and-management-guides/stvault-disconnect-guide.md) (initiate voluntary disconnect, apply oracle report, abandon Dashboard, accept ownership). -7. **Withdraw assets** from the Staking Vault and **distribute them to users** via the Distributor. - -Steps 1–5 are DeFi Wrapper-specific and covered below. Step 6 follows the standard stVault disconnect flow. Step 7 covers asset distribution and user claiming. - ---- - -## Before you start: get contract addresses - -To view all contract addresses for your pool at once: - -```bash -yarn start dw info -``` - -This prints the Vault, Dashboard, WithdrawalQueue, Distributor, and other addresses in a single command. You will need these addresses throughout the guide. - ---- - -## Step 1. Assign required roles - -The disconnect process requires multiple roles across the Pool, Withdrawal Queue, and Dashboard contracts. Grant these roles to a trusted actor via the Timelock Controller. - -| Role | Contract | Purpose | -| ----------------------------------- | ---------------- | ------------------------------------------------------------- | -| `LOSS_SOCIALIZER_ROLE` | Pool | Force rebalance undercollateralized users | -| `DEPOSITS_PAUSE_ROLE` | Pool | Pause new deposits | -| `MINTING_PAUSE_ROLE` | Pool | Pause stETH minting | -| `WITHDRAWALS_PAUSE_ROLE` | Withdrawal Queue | Pause new withdrawal requests | -| `FINALIZE_ROLE` | Withdrawal Queue | Finalize pending withdrawal requests | -| `TRIGGER_VALIDATOR_WITHDRAWAL_ROLE` | Dashboard | Force validator exits | -| `REBALANCE_ROLE` | Dashboard | Rebalance the vault | -| `VOLUNTARY_DISCONNECT_ROLE` | Dashboard | Call `voluntaryDisconnect()` directly (Step 6) | -| `COLLECT_VAULT_ERC20_ROLE` | Dashboard | Transfer wstETH from vault to Distributor via `collectERC20` (Step 7.2) | -| `MANAGER_ROLE` | Distributor | `add-token`, `distribute`, and Merkle root updates (Steps 7.3–7.4); pre-granted to `--nodeOperatorManager` unless a different actor distributes | - -:::info -`VOLUNTARY_DISCONNECT_ROLE` is only needed if `trustedActor` calls `voluntaryDisconnect()` directly. If using a Timelock Controller that already holds `DEFAULT_ADMIN_ROLE` on the Dashboard, this grant can be skipped. - -`COLLECT_VAULT_ERC20_ROLE` is only needed if `trustedActor` (not the vault owner) performs Step 7.2 (`collect-erc20`). - -::: - -Schedule and execute a batch transaction through the Timelock Controller to grant the roles below. The example covers the seven grants that match the Pool, Withdrawal Queue, and Dashboard **rebalance / pause / exit** path. If `trustedActor` must also call `voluntaryDisconnect()` or `collectERC20` on the Dashboard without going through an admin Timelock, append two more `grantRole` calls on the Dashboard for `VOLUNTARY_DISCONNECT_ROLE` and `COLLECT_VAULT_ERC20_ROLE`. `MANAGER_ROLE` is on the Distributor — grant it separately if the distributor is managed by a different address than `--nodeOperatorManager`. - -``` -targets: [Pool, Pool, Pool, WithdrawalQueue, WithdrawalQueue, Dashboard, Dashboard] -payloads: [ - grantRole(LOSS_SOCIALIZER_ROLE, trustedActor), - grantRole(DEPOSITS_PAUSE_ROLE, trustedActor), - grantRole(MINTING_PAUSE_ROLE, trustedActor), - grantRole(WITHDRAWALS_PAUSE_ROLE, trustedActor), - grantRole(FINALIZE_ROLE, trustedActor), - grantRole(TRIGGER_VALIDATOR_WITHDRAWAL_ROLE, trustedActor), - grantRole(REBALANCE_ROLE, trustedActor) -] -``` - ---- - -## Step 2. Exit all validators - -Exit all validators associated with the Staking Vault. This moves ETH from the Beacon Chain back to the vault balance. - -- **Voluntary exit:** Request exits through your standard validator management tooling. -- **Forced exit:** If voluntary exits are not possible, call `Dashboard.triggerValidatorWithdrawals()` from an account with `TRIGGER_VALIDATOR_WITHDRAWAL_ROLE`: - -```bash -yarn start contracts dashboard w trigger-validator-withdrawal -``` - -:::info -The `triggerValidatorWithdrawals` call requires sending a small withdrawal fee (currently ~10 gwei per validator) to cover the EIP-7002 triggerable withdrawal fee. The `` address receives any excess fee refund after the withdrawal is processed. -::: - -Wait for all validator exits to complete and ETH to be swept back to the Staking Vault balance before proceeding. - ---- - -## Step 3. Pause withdrawals and finalize pending requests - -### 3.1. Pause new withdrawal requests - -Prevent users from creating new withdrawal requests by calling `WithdrawalQueue.pauseWithdrawals()` from an account with `WITHDRAWALS_PAUSE_ROLE`: - -```bash -yarn start dw c wq w pause -``` - -### 3.2. Finalize all pending withdrawal requests - -Before disconnecting, all pending withdrawal requests must be finalized. - -An oracle report may be required before finalization to update the vault state. Apply a fresh report if needed. - -Call `WithdrawalQueue.finalize(maxRequests, gasCostCoverageRecipient)` from an account with `FINALIZE_ROLE`: - -```bash -yarn start dw c wq w finalize -``` - -After finalization, verify all requests are processed — the following should all return `0`: - -```bash -yarn start dw c wq r unfinalizedRequestsNumber -yarn start dw c wq r unfinal-stv -yarn start dw c wq r unfinal-assets -``` - ---- - -## Step 4. Pause deposits and minting - -### 4.1. Pause deposits - -Call `Pool.pauseDeposits()` from an account with `DEPOSITS_PAUSE_ROLE`: - -```bash -yarn start dw c stv w pause-deposits -``` - -### 4.2. Pause minting - -Call `Pool.pauseMinting()` from an account with `MINTING_PAUSE_ROLE`: - -```bash -yarn start dw c stv-steth w pause-minting -``` - -After pausing, any attempts to deposit ETH, mint stETH shares, or mint wstETH will revert. - ---- - -## Step 5. Rebalance the Staking Vault to zero liability - -### 5.1. Force rebalance undercollateralized users (if any) - -If any pool users are undercollateralized (their stETH liability exceeds the value of their STV), their position should be force-closed before disconnect. Skipping this step is technically possible — `rebalanceVaultWithShares` will still bring vault liability to zero — but the shortfall will be silently covered by vault ETH, effectively distributing the loss across all other users without burning the undercollateralized user's STV. - -To avoid this, force-close each unhealthy position by calling `Pool.forceRebalanceAndSocializeLoss()` from an account with `LOSS_SOCIALIZER_ROLE`: - -```bash -yarn start dw uc h w force-rebalance-and-socialize-loss -``` - -This burns the user's STV, repays their stETH liability as far as possible, and socializes any remaining shortfall across all pool participants. To preview the operation without executing it, add `--dry-run`. - -:::info -To identify undercollateralized accounts, use the health monitoring command: - -```bash -yarn start dw uc h r list-unhealthy -``` - -This lists all positions that have breached the forced rebalance threshold. Run `force-rebalance-and-socialize-loss` for each account in the output. -::: - -:::warning -`forceRebalanceAndSocializeLoss` requires a fresh oracle report. Apply one before running this step. - -The pool has a `maxLossSocializationBP` limit (default `0`) that caps how much loss can be socialized in a single call. The CLI sets this automatically, but if the shortfall exceeds the limit the transaction will revert with `ExcessiveLossSocialization`. In that case, contact your protocol administrator to adjust the limit. -::: - -### 5.2. Rebalance the vault - -Check the current liability: - -```bash -yarn start contracts dashboard r liability-shares -``` - -Call `Dashboard.rebalanceVaultWithShares(liabilityShares)` from an account with `REBALANCE_ROLE`, passing the full `liabilityShares` amount to bring the liability to zero: - -```bash -yarn start contracts dashboard w rebalance-shares -``` - -:::warning -The disconnect will revert with `NoLiabilitySharesShouldBeLeft` if any liability shares remain. Ensure `Dashboard.liabilityShares()` returns `0` before proceeding. -::: - ---- - -## Step 6. Disconnect the stVault - -Follow the [stVault Disconnect Guide](../../operational-and-management-guides/stvault-disconnect-guide.md) to complete the disconnection: - -1. **Initiate voluntary disconnect** — schedule and execute `Dashboard.voluntaryDisconnect()` through the Timelock Controller. Requires a fresh oracle report. -2. **Apply the next oracle report** — finalizes the disconnection. -3. **Abandon Dashboard** — call `Dashboard.abandonDashboard(newOwner)` from the Timelock Controller. -4. **Accept ownership** — call `StakingVault.acceptOwnership()` from the `newOwner` address. - ---- - -## Step 7. Withdraw assets and distribute to users - -After disconnection, remaining ETH in the vault must be distributed to pool users through the Distributor contract. - -### 7.1. Convert vault ETH to wstETH - -The Distributor contract does not accept raw ETH or wETH. wstETH is used because it preserves yield-bearing properties — users continue accruing staking rewards while holding it, whereas wETH is a plain ETH wrapper with no yield. - -The conversion leverages the wstETH contract's `receive()` function, which automatically stakes incoming ETH and mints wstETH back to the sender. This means you can convert the vault's ETH to wstETH in a single `withdraw` call. - -First, retrieve the available balance of the vault: - -```bash -yarn start contracts vault r available-balance -``` - -Use the value returned as `` in the next command. Call `StakingVault.withdraw(recipient, amount)` with the **wstETH contract address** as the recipient: - -```bash -yarn start contracts vault w withdraw -``` - -After this call, the vault holds wstETH tokens (not ETH). - -:::info -Make sure you account for the Initial Connect Deposit (1 ETH) that was unlocked after disconnect — it is now part of the available balance. -::: - -### 7.2. Transfer wstETH to the Distributor - -First, retrieve the wstETH balance of the vault: - -```bash -yarn start account r info -``` - -Then send the wstETH from the vault to the Distributor contract using `collectERC20`, passing the retrieved ``: - -```bash -yarn start contracts vault w collect-erc20 -``` - -### 7.3. Add wstETH as a supported distribution token - -If wstETH is not yet registered in the Distributor, add it: - -```bash -yarn start dw uc distributor w add-token -``` - -### 7.4. Generate the Merkle tree, upload to IPFS, and set the root - -The CLI provides a single command that handles the entire distribution flow: - -1. Calculates each user's share based on their balance at the time of distribution. -2. Builds a Merkle tree mapping each user to their cumulative claimable amount. -3. Transfers tokens to the Distributor contract (if not already transferred). -4. Sets the Merkle root and CID on-chain. -5. Saves file locally so you can upload and pin to IPFS provider of choice - -```bash -yarn start dw uc distributor w distribute \ - --mode=snapshot \ - --output-path ./distribution.json -``` - -**Options:** - -| Option | Description | -| --------------------------------------------- | ------------------------------------------------------------------------- | -| `--blacklist ` | Addresses to exclude from distribution | -| `--from-block ` / `--to-block ` | Block range for processing transfer events | -| `--output-path ` | Path to save the distribution JSON | -| `--upload [pinningUrl]` | Upload the Merkle tree to an IPFS pinning service | -| `--skip-transfer` | Skip transferring tokens to the Distributor (if already done in step 7.2) | -| `--skip-set-root` | Generate the tree without setting the root on-chain | -| `--skip-write` | Skip writing the distribution JSON to file | - -:::info -Since tokens were already transferred to distributor in step 7.2, use `--skip-transfer` to avoid a duplicate transfer: - -```bash -yarn start dw uc distributor w distribute \ - --skip-transfer \ - --mode=snapshot \ - --output-path= -``` - -::: - -:::info -The caller must have `MANAGER_ROLE` on the Distributor contract. This role is granted upon pool creation to the `--nodeOperatorManager` address. -::: - -### 7.5. Verify the distribution - -Check the Distributor state to confirm the distribution was successful: - -```bash -yarn start dw uc distributor r state -``` - -Verify the following fields in the output: - -- **Merkle Root** — must be a non-zero value, indicating the Merkle tree has been set -- **CID** — must contain a valid IPFS CID, confirming the distribution data was uploaded to IPFS. You can open the CID via an IPFS gateway to inspect which tokens and amounts were distributed -- **Last Processed Block** — shows the block number at which the distribution was made - -### 7.6. Upload distribution to IPFS and pin the file - -Upload the saved `distribution.json` manually to your IPFS pinning provider. - -When uploading, ensure the resulting CID is in **CIDv0 format** (starts with `Qm`). CIDv1 CIDs are not supported. Most pinning services produce CIDv0 by default when uploading a raw file. - -Pin the file with your provider to ensure it remains accessible. After pinning, you can verify the content is reachable via any IPFS gateway. - -### 7.7. Distribution complete - -The distribution is now configured. Users can verify their allocation by opening the CID via an IPFS gateway and locating their address in the Merkle tree. - -Users can claim their funds — see [User: claiming funds](#user-claiming-funds) below. - ---- - -## User: claiming funds - -After the operator has distributed assets and published the Merkle tree, users can claim their share on the UI. - -:::info -For `stvStrategyPool` users must first request withdrawal from the underlying DeFi strategy before claiming distributed funds. This pulls funds from the strategy vault back to the proxy balance. The strategy address was shown at pool creation time — if you no longer have it, ask the pool operator. -::: - -### Claiming with UI - -:::info -If the UI is unavailable, contact the pool operator for contract addresses and run the UI locally, or use the CLI commands in the next section. -::: - -Even when vault is disconnected users will be able to use UI: - -- request and claim withdrawals from underlying strategy vaults -- claim any previous claimable withdrawals from pool's `WithdrawalQueue` -- claim any distributed funds. In case of `stvStrategyPool`, tokens are distributed to proxies but funds can be claimed via UI - -### Claiming with CLI - -#### Claim distributed funds - -If you want you can claim funds on behalf of the users via CLI, but this will produce 1 transaction per user per token(batch transactions are supported via CLI and WalletConnect) - -Claim: - -```bash -yarn start dw uc distributor w claim -``` - -You can adjust command with options: - -- `--recipients [addresses...]` - listing only specific address to claim for -- `--tokens [addresses...]` - listing only specific tokens to claim -- `--print-only` - only print planned claim - -#### stvStrategyPool: claiming distributed funds via CLI - -For `stvStrategyPool` the Distributor distributes tokens to each user's **strategy proxy** contract, not directly to the user's wallet. To receive funds, users must first claim to the proxy, then transfer from the proxy to their wallet. - -**Step 1.** Find your proxy address: - -```bash -yarn start dw c str r proxy-of -``` - -**Step 2.** Claim wstETH to your proxy from the Distributor: - -```bash -yarn start dw uc distributor w claim --recipients -``` - -**Step 3.** Transfer wstETH from the proxy to your wallet: - -```bash -yarn start dw c str w safe-transfer-erc20 -``` - -The `` is in decimal wstETH format (e.g. `1.5`), not raw wei. - -:::info -The strategy address was provided at pool creation time via `create-strategy-pool-lido-earn-eth`. If you no longer have it, ask the pool operator. -::: - -### Claiming ETH from previously requested withdrawals with CLI - -If the user had requested withdrawals before the disconnect, those requests were finalized by the operator during [Step 3](#step-3-pause-withdrawals-and-finalize-pending-requests). The ETH is ready but still held by the Withdrawal Queue — the user must explicitly claim it to receive it in their wallet. - -First, retrieve the user's withdrawal request IDs: - -```bash -yarn start dw c wq r withdrawalRequestsOf -``` - -Then claim the withdrawal(s): - -```bash -# Claim a single request -yarn start dw c wq w claim-withdrawal - -# Claim multiple requests -yarn start dw c wq w claim-withdrawals -``` - -:::info -The Withdrawal Queue remains functional for claims even after the pool is disconnected. Users can claim at any time. -::: diff --git a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/index.md b/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/index.md deleted file mode 100644 index b65170d44..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/index.md +++ /dev/null @@ -1,508 +0,0 @@ ---- -sidebar_position: 1 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# 🌊 End-user staking product by DeFi Wrapper - -## Intro - -**The DeFi Wrapper** is a no-/low-code toolkit that lets builders, Node Operators, and platforms launch customized user-facing staking products powered by stVaults — with optional automated APR-boosting strategies such as leverage loops or any custom stETH-based yield module. - -This guide walks through the concepts and practical steps to launch such a product without deep protocol knowledge. - -## What you can build - -DeFi Wrapper supports three product archetypes: - -### 1. Pooled delegated staking - -![Pooled delegated staking](/img/stvaults/guide-pooled-staking-product/wrapped_products_pooled.png) - -- Users stake ETH with the same Node Operator. -- Users receive APR from validator performance. - -**Use case:** End-user staking product with conservative validation-based APR and a user-friendly interface embedded in your own traffic channel or a partner channel. - -### 2. Pooled delegated liquid staking - -![Pooled delegated liquid staking](/img/stvaults/guide-pooled-staking-product/wrapped_products_liquid.png) - -- Users stake ETH with the same Node Operator. -- Users receive stETH (within the stVault’s Reserve Ratio). -- Users receive APR from validator performance. - -**Use case:** Institution-targeted individual (whitelisted) staking product with conservative validation-based APR and liquidity, and a simple user interface hosted on the Node Operator's web server. - -### 3. Pooled delegated staking with boosted APR - -#### 3.1. Leveraged staking (looping) - -![Boosted APR via leveraged staking (looping)](/img/stvaults/guide-pooled-staking-product/wrapped_products_looping.png) - -- Users stake ETH with the same Node Operator. -- stETH is minted automatically and deposited into the connected looping strategy (pre-integrated or custom). -- ETH is borrowed against stETH and deposited back into the stVault, increasing the stVault's total value and the amount of ETH on validators. -- Users receive boosted APR from validator performance. - -**Use case:** End-user staking product with higher risk/yield profile through the connected curated looping strategy, increasing the amount of ETH on validators. The product lets the Node Operator attract more ETH for validation than end users deposit. - -#### 3.2. DeFi strategy (custom) - -![Boosted APR via DeFi strategy](/img/stvaults/guide-pooled-staking-product/wrapped_products_defi.png) - -- Users stake ETH with the same Node Operator. -- stETH is minted automatically and deposited into the connected DeFi strategy (leveraged staking or any custom stETH-based module). -- Users receive APR from validator performance + strategy APR. - -**Use case:** End-user staking product with higher risk/yield profile through the connected curated DeFi strategy, making the product more attractive for end users. - -## Environments - -- [CLI](https://lidofinance.github.io/lido-staking-vault-cli/get-started/configuration) -- [UI template](https://github.com/lidofinance/defi-wrapper-widget) - - - - - - - - - - -## Steps - -### 1. Create a tokenized staking vault (pool) - -The easiest way to create a tokenized staking vault (pool) is to use the [stVaults CLI](https://lidofinance.github.io/lido-staking-vault-cli). -It's a command-line tool for managing both staking vaults and DeFi Wrapper pools. It deploys a pool plus its underlying staking vault via the [`Factory`](https://github.com/lidofinance/vaults-wrapper/blob/develop/src/Factory.sol) contract. - -The CLI performs the deployment in two transactions to stay within the current 16M transaction gas limit. - -To start: - -- Set up the CLI according to the [README](https://github.com/lidofinance/lido-staking-vault-cli/blob/develop/README.md). -- Prepare a valid CLI configuration — see the [configuration tutorial](https://lidofinance.github.io/lido-staking-vault-cli/get-started/configuration). - -:::info - -The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the vault upon connection to Lido `VaultHub`. - -The newly created staking vault is automatically connected to Lido `VaultHub` and placed into the default tier. Placement into non-default tiers right upon deployment is not supported. - -::: - -To list the available pool types and creation commands, run: - -```bash -yarn start defi-wrapper contracts factory write -h -``` - -:::info - -For each pool type, the CLI prints the environment variables required for the UI setup. -Keep this output if you plan to set up the UI. - -::: - -#### Deployment of `StvPool` (pool without stETH minting) - -Run `yarn start defi-wrapper contracts factory write create-pool-stv -h` for the description of the required STV pool parameters. - -Start the deployment like: - -```bash -yarn start defi-wrapper contracts factory w create-pool-stv \ - --nodeOperator 0x0000000000000000000000000000000000000001 \ - --nodeOperatorManager 0x0000000000000000000000000000000000000002 \ - --nodeOperatorFeeRateBP 10 \ - --confirmExpiry 86400 \ - --minDelaySeconds 3600 \ - --minWithdrawalDelayTime 3600 \ - --name "Debug STV Pool" \ - --symbol STV \ - --proposer 0x0000000000000000000000000000000000000003 \ - --executor 0x0000000000000000000000000000000000000004 \ - --emergencyCommittee 0x0000000000000000000000000000000000000005 \ - --allowList false -``` - -#### Deployment of `StvStETHPool` (pool with stETH minting) - -Run `yarn start defi-wrapper contracts factory write create-pool-stv-steth -h` for the description of the required STV pool parameters. - -Start the deployment like: - -```bash -yarn start defi-wrapper contracts factory w create-pool-stv-steth \ - --nodeOperator 0x0000000000000000000000000000000000000001 \ - --nodeOperatorManager 0x0000000000000000000000000000000000000002 \ - --nodeOperatorFeeRateBP 10 \ - --confirmExpiry 86400 \ - --minDelaySeconds 3600 \ - --minWithdrawalDelayTime 3600 \ - --name "Debug STV Pool" \ - --symbol STV \ - --proposer 0x0000000000000000000000000000000000000003 \ - --executor 0x0000000000000000000000000000000000000004 \ - --emergencyCommittee 0x0000000000000000000000000000000000000005 \ - --reserveRatioGapBP 250 \ - --allowList false -``` - -:::warning - -The minimum recommended value for `reserveRatioGapBP` is `250` (2.5%). It is expected to be sufficient to absorb enough of the vault's performance volatility to keep users' positions healthy in most cases. - -::: - -#### Deployment of `StvStrategyPool` with a custom strategy - -To deploy a pool integrated with a custom DeFi strategy see the dedicated guide: [Pool with a custom strategy](./custom-strategy). The guide covers both deploying a new pool with a strategy from scratch and upgrading an existing `StvStETHPool` to a strategy pool. - -#### Deployment of `StvStrategyPool` with the `Lido Earn ETH` strategy - -The pool with the `Lido Earn ETH` strategy: ETH is deposited to validators and generates staking rewards, stETH is minted and automatically deposited to the Earn ETH strategy to earn additional rewards. Deposited stETH is distributed across a curated set of high-performing DeFi strategies, including lending markets and LP positions. The `Earn ETH` strategy is built on Mellow architecture, so the strategy connector is called "MellowStrategy", and the factory is called "MellowStrategyFactory". - -To deploy this pool, use the `create-strategy-pool-lido-earn-eth`. The factory addresses for each network are listed in the [Environments](#environments) section. The full parameter reference is available below. - -Start the deployment like: - -```bash -yarn start defi-wrapper contracts factory w create-strategy-pool-lido-earn-eth \ - --nodeOperator \ - --nodeOperatorManager \ - --nodeOperatorFeeRateBP 10 \ - --confirmExpiry 86400 \ - --minDelaySeconds 3600 \ - --minWithdrawalDelayTime 3600 \ - --name "Staked Earn ETH Pool" \ - --symbol STV \ - --proposer \ - --executor \ - --emergencyCommittee \ - --reserveRatioGapBP 250 -``` - -You can use `--allowList true` to enable the deposit allowlist for this strategy. AllowList Manager role on Strategy must be set separately by TimeLock governance. - -:::warning -AllowList will be always enabled on StvStethPool contract. This allowlist ensures only the strategy contract can deposit into the pool, and minting is required to produce wstETH for the Earn ETH Vault. Strategy contract has its own allow list. -::: - -
- Parameter reference - -| Parameter | Description | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| `` | DeFi Wrapper Factory contract address (see [Environments](/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/#environments)) | -| `` | Lido Earn ETH Strategy Factory contract address (see [Environments](/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/#environments)) | -| `--nodeOperator` | Address of the Node Operator managing validators | -| `--nodeOperatorManager` | Address authorized to manage Node Operator settings | -| `--nodeOperatorFeeRateBP` | Node Operator fee in basis points (10 = 0.1%) | -| `--confirmExpiry` | Confirmation timeout in seconds | -| `--minDelaySeconds` | TimeLock minimum delay before execution | -| `--minWithdrawalDelayTime` | Minimum delay before withdrawals can be finalized | -| `--name` | ERC-20 pool share token name | -| `--symbol` | ERC-20 pool share token symbol | -| `--proposer` | Address authorized to propose TimeLock operations | -| `--executor` | Address authorized to execute TimeLock operations | -| `--emergencyCommittee` | Address that can pause pool operations | -| `--reserveRatioGapBP` | Reserve ratio gap in basis points (recommended min: 250) | - -
- -##### Managing AllowList for `StvStrategyPool` with `Lido Earn ETH` strategy - -Due to design the allow list for `StvStrategyPool` is always on and is limited only to the strategies contracts attached to the pool. The strategy contract(if enabled by `--allowList true`) has it's own allow list. To manage the Strategy allow list, use the following CLI commands: - -- `yarn start defi-wrapper use-cases wrapper-operations read info ` to check the current strategy address attached to the pool -- `yarn start defi-wrapper use-cases tinmelock-governance common read get-timelock-address ` to get the timelock address for the pool -- `yarn start defi-wrapper use-cases wrapper-operations read allow-list ` to check the current allow list state for the strategy -- `yarn start defi-wrapper use-cases timelock-governance strategy write propose-grant-role ALLOW_LIST_MANAGER_ROLE ` AS PROPOSER to propose adding a manager to the strategy allow list -- `yarn start defi-wrapper use-cases timelock-governance strategy write execute-grant-role ALLOW_LIST_MANAGER_ROLE ` AS EXECUTOR to execute adding a manager to the strategy allow list after the timelock delay has passed -- `yarn start defi-wrapper use-cases wrapper-operations read allow-list ` to verify that state was updated -- `yarn start defi-wrapper use-cases wrapper-operations write allow-list-add/allow-list-remove ` as holder of ALLOW_LIST_MANAGER_ROLE to add or remove an address from the strategy allow list - -### 2. Create Web UI - -Follow this [guide](https://github.com/lidofinance/defi-wrapper-widget/blob/develop/README.md) to: - -- Clone the provided repository -- Use addresses outputted by CLI to fill up `.env` -- Adjust titles, logos, texts, and color scheme to your liking -- Deploy the dApp - -### 3. Adjust stETH minting parameters - -By default, a newly created stVault is connected to the Default tier with a Reserve Ratio of 50%. If the Node Operator has passed identification and been granted individual tiers, the stVault can be moved from the Default tier to one of the Node Operator’s tiers to access better stETH minting conditions. - -For more information about stVault tiers please see [Adjust stETH minting parameters](../basic-stvault#adjust-steth-minting-parameters). - -For pooled vaults the process of changing tier is a bit different because the Vault Owner role is assigned to the Timelock contract. The Timelock contract itself implements a two-step process for performing an on-chain action. First, the holder of its proposer role creates a proposed on-chain action; second, after a time period, the holder of the executor role executes it. - -Thus, changing tier for a pooled vault is a three-step process: - -1. Holder of the Timelock's proposer role calls `TimelockController.schedule` to propose the `OperatorGrid.changeTier` call -2. After the timelock period, the holder of the Timelock's executor role calls `TimelockController.execute` for the scheduled proposal -3. Within the confirmation time window period (default 24 hours), the Node Operator calls `OperatorGrid.changeTier` with the same parameters - -Confirming tier change request requires applying fresh report to vault. [Read more about applying reports](../../operational-and-management-guides/applying-report-guide) - -**Parameters needed for this step:** - -- `VaultAddress`: the address of the `Vault` contract. -- `TierID`: the ID of the tier to which the stVault will be connected. -- `RequestedShareLimit`: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier's stETH limit. -- `TimelockAddress`: the address of the `TimelockController` contract (deployed together with the pool). -- `OperatorGridAddress`: the address of the `OperatorGrid` contract (available in the stVaults contract addresses list, see [#Environments](#environments)). - -
- How to determine available tier IDs for your Node Operator - -To find out which tier IDs are available for your Node Operator, you can use: - -**CLI:** - -```bash -# Get group information for your Node Operator (shows all available tier IDs) -yarn start contracts operator-grid r group - -# Get information about a specific tier -yarn start contracts operator-grid r tier -``` - -**Contract call (Etherscan):** - -- Navigate to the `OperatorGrid` contract address -- Go to **Contract** → **Read Contract** -- Call `group(nodeOperatorAddress)` to get the `Group` struct, which includes the `tierIds` array -- Call `tier(tierId)` to get details about a specific tier - -The `group` method returns a struct containing: - -- `operator`: Node operator address -- `shareLimit`: Maximum liability shares across all group vaults -- `liabilityShares`: Current liability shares in the group -- `tierIds`: Array of tier IDs belonging to this Node Operator - -
- -
- Step 1: Schedule the tier change (Proposer) - -#### CLI - -Use `--wallet-connect` option for all commands or provide private key to CLI `.env` - -1. Get address of your timelock contract: - ```bash - yarn start defi-wrapper use-cases timelock-governance common read get-timelock-address - ``` -2. Connect wallet that holds the proposer role to CLI -3. Propose change tier - ```bash - yarn start defi-wrapper use-cases timelock-governance dashboard write propose-change-tier - ``` - -#### Etherscan - -1. Open **Etherscan** and navigate to the **TimelockController** contract by its address. -2. Go to the **Contract** tab → **Write Contract**. -3. Click **Connect to Web3** and connect the wallet that holds the **proposer role**. -4. Find the `schedule` method in the list and fill out the fields: - - `target`: the `OperatorGrid` contract address. - - `value`: `0` (no ETH is sent with this call). - - `data`: the ABI-encoded call to `changeTier(address vault, uint256 tierId, uint256 requestedShareLimit)`. You can generate this using tools like [ABI Encoder](https://abi.hashex.org/) or cast from Foundry: - ```bash - cast calldata "changeTier(address,uint256,uint256)" - ``` - - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000` (no predecessor required). - - `salt`: `0x0000000000000000000000000000000000000000000000000000000000000000` (or any unique value if you need to differentiate identical operations). - - `delay`: the delay in seconds (must be at least the `minDelaySeconds` configured during pool deployment). -5. Click **Write** and sign the transaction in your wallet. -6. Click **View your transaction** and wait for it to be executed. -7. Note down the **operation ID** from the `CallScheduled` event in the transaction logs — you will need it to verify the operation status before execution. - -
- -
- Step 2: Execute the scheduled tier change (Executor) - -#### CLI - -1. Check the timelock delay period: - - ```bash - # Get timelock address - yarn start defi-wrapper use-cases timelock-governance common read get-timelock-address - - # Then get the minimum delay (replace with the address from previous command) - yarn start defi-wrapper use-cases timelock-governance common read get-min-delay - ``` - -2. Wait for the timelock delay period to pass. You can verify the operation is ready by calling - ```bash - yarn start defi-wrapper use-cases timelock-governance common read get-last-operations - ``` -3. Connect wallet that holds the executor role to CLI -4. Execute change tier - ```bash - yarn start defi-wrapper use-cases timelock-governance dashboard write execute-change-tier - ``` - -#### Etherscan - -1. Check the timelock delay period: - - - Open **Etherscan** and navigate to the **TimelockController** contract by its address. - - Go to the **Contract** tab → **Read Contract**. - - Find the `getMinDelay` method and click **Query** to see the minimum delay in seconds. - -2. Wait for the timelock delay period to pass. You can verify the operation is ready by calling `isOperationReady(operationId)` on the TimelockController contract (in **Read Contract** tab). -3. Execute change tier, connect the wallet: - - Open **Etherscan** and navigate to the **TimelockController** contract by its address. - - Go to the **Contract** tab → **Write Contract**. - - Click **Connect to Web3** and connect the wallet that holds the **executor role**.Click **Connect to Web3** and connect the wallet that holds the **executor role**. -4. Find the `execute` method in the list and fill out the fields with the **same values** used in the `schedule` call: - - `target`: the `OperatorGrid` contract address. - - `value`: `0`. - - `payload`: the same ABI-encoded call data used in step 1. - - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000`. - - `salt`: the same salt value used in step 1. -5. Click **Write** and sign the transaction in your wallet. -6. Click **View your transaction** and wait for it to be executed. - -
- -
- Step 3: Confirm the tier change (Node Operator) - -Within the confirmation time window period (default 24 hours) after step 2, the Node Operator must confirm the tier change: - -#### stVaults UI - -1. Go to `https://stvaults.lido.fi/vaults/[vaultAddress]/settings/tier` -2. Connect wallet that has Node operator address -3. Follow UI to confirm tier change - -#### CLI - -1. Connect wallet that has Node operator address to CLI -2. `yarn start vo w change-tier-by-no -v -r ` - -#### Etherscan - -1. Open **Etherscan** and navigate to the **OperatorGrid** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet registered as the **Node Operator**. -5. Find the `changeTier` method in the list and fill out the fields with the **same values** used in steps 1 and 2: - - `vault`: the `Vault` contract address. - - `tierId`: the tier ID. - - `requestedShareLimit`: the requested share limit. -6. Click **Write** and sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -### 4. Deposit ETH to validators - -Supplying ETH to the stVault increases its balance. The Node Operator can then deposit ETH from this balance into validators. - -**The Predeposit Guarantee (PDG)** contract, as part of the stVaults platform, helps prevent deposit frontrunning caused by the vulnerabilities described in [LIP-5](https://research.lido.fi/t/lip-5-mitigations-for-deposit-front-running-vulnerability/1269). PDG secures the Vault Owner’s ETH deposits to validators from being front-run by the Node Operator. - -One of the key benefits of using PDG is the avoidance of commingling: it keeps the finances of the Vault Owner and the Node Operator strictly separated. - -PDG enables three main use cases: - -- **Full-cycle proof of validators.** Enables a non-custodial deposit mechanism by using guarantee ETH as collateral. [Follow the main guide](../../tech-documentation/pdg#full-cycle-trustless-path-through-pdg). -- **PDG shortcut.** Allows skipping the pre-deposit steps and depositing directly to a validator without using PDG initially. The validator can later be associated with the vault by proving it through PDG. This path is applicable when there is unconditional trust between the Node Operator and the Vault Owner. [Follow the shortcut guide](../../tech-documentation/pdg#pdg-shortcut). -- **Adding existing validators.** Lets you connect an existing validator from external staking infrastructure to an stVault as an advanced integration use case. [Consolidations guide](../../tech-documentation/consolidation) - -Read more: [Technical details](https://hackmd.io/@lido/stVaults-design#315-Essentials-PredepositGuarantee); [GitHub Repository](https://github.com/lidofinance/core/blob/feat/vaults/contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol). - -### 5. Monitor stVault health and rebalance - -The key stVault metrics that the Vault Owner should monitor and control are: - -- **Utilization ratio** — the share of the stETH minting capacity currently used by the Vault Owner. [Learn more](../../features-and-mechanics/parameters-and-metrics) -- **Health Factor** — a metric that reflects the economic state of the vault. It shows how the stETH liability is collateralized by the Total Value. A Health Factor of 100% corresponds to the Forced Rebalance Threshold, meaning that if the Health Factor falls below 100%, the stVault becomes subject to forced rebalancing. [Learn more](../../features-and-mechanics/parameters-and-metrics) - -Read more: - -- [Health Monitoring Guide](../../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../../operational-and-management-guides/health-emergency-guide.md) - -The Health Factor metric may decrease as a result of validator underperformance, penalties, or a slashing event. - -If this happens, there are three main options available: - -- Supply ETH to increase Total Value. -- Repay stETH to reduce stETH liability. -- Rebalance ETH (optionally combined with a supply in a single transaction). - -**Rebalancing** involves transferring available ETH from the stVault balance to Lido Core, receiving stETH at a 1:1 ratio, and repaying it back to the stVault. This reduces stETH liability and thereby increases the Health Factor. - -Rebalancing is performed in one transaction. - -The amount of ETH required for rebalancing to bring the Utilization Ratio to 100% depends on the current Health Factor and Reserve Ratio. It can be pre-calculated manually using the formula, or via the built-in methods. - -
- by Formula - - ETH for rebalance = (stETH Liability − (1 − Reserve Ratio) × Total Value) / Reserve Ratio - -
-
- by Command-line Interface - - See the [CLI documentation](https://lidofinance.github.io/lido-staking-vault-cli/) for rebalance commands. - -
-
- using Etherscan UI - 1. Open **Etherscan** and navigate to the **VaultHub** contract by its address (available in the stVaults contract addresses list, see [#Environments](#environments)). - 2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 3. Open the **Contract** tab → **Read as Proxy**. - 4. Click **Connect to Web3** and connect your wallet in the dialog window. - 5. Find the method `healthShortfallShares` in the list, fill out the input with the `vault` contract address, and click **Query**. - 6. Receive the result right under the submit button. -
- -## DeFi Wrapper roles and permissions - -For DeFi Wrapper-specific roles (Pool, Withdrawal Queue, Distributor, Strategy, Timelock), see [DeFi Wrapper roles and permissions](./roles-and-permissions). - -For operating withdrawals (queue monitoring, liquidity, finalization), see [Withdrawals operations](./withdrawals). - -For stVaults roles (Vault/Dashboard/PDG), see [stVaults Roles and permissions](../../features-and-mechanics/roles-and-permissions). - -## Useful links - -- [DeFi Wrapper Technical Design](https://hackmd.io/@lido/lido-v3-wrapper-design) -- [stVaults Roles](../../features-and-mechanics/roles-and-permissions) -- [stVaults Metrics](../../features-and-mechanics/parameters-and-metrics) -- [Health Monitoring Guide](../../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../../operational-and-management-guides/health-emergency-guide.md) diff --git a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/roles-and-permissions.md b/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/roles-and-permissions.md deleted file mode 100644 index fa59eeda5..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/roles-and-permissions.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -sidebar_position: 2 ---- - -# 🔐 DeFi Wrapper roles and permissions - -This page describes **DeFi Wrapper-specific roles** for pooled staking products. For **stVaults roles**, see [stVaults Roles and permissions](/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions). - -DeFi Wrapper is deployed as a set of on-chain contracts (Pool, Withdrawal Queue, Distributor, optional Strategy) connected to a stVault (Vault + Dashboard). Access is controlled by a combination of: - -- **`TimelockController` governance** (proposer/executor with a mandatory delay) -- **Role-based access control** (`AccessControl` roles on Pool/WithdrawalQueue/Distributor/Dashboard) -- **Emergency Committee** (fast “pause” capabilities) - -## TimelockController roles (governance) - -:::info -Use CLI `yarn start defi-wrapper use-cases timelock-governance --help` to get list of commands to operate TimelockController. There are shortcut commands for governing roles and other common operations for the DeFi wrapper. -::: - -`TimelockController` is deployed together with the pool and becomes the admin for most DeFi Wrapper components. It is **self-administered**, meaning role changes and privileged actions should go through timelocked proposals. - -**Proposer** – the entity responsible for proposing an upgrade. By default, this actor is the Vault owner. - -**Executor** – the entity responsible for accepting the upgrade. This may be a committee of independent security experts trusted by both the vault owner and its users. - -| Role | Where | Permissions | -| --------------- | -------------------- | -------------------------------------------------------------------------------------------------------- | -| `PROPOSER_ROLE` | `TimelockController` | Schedule operations (`schedule`); proposers also get `CANCELLER_ROLE` (can cancel scheduled operations). | -| `EXECUTOR_ROLE` | `TimelockController` | Execute ready operations (`execute`). | - -## Pool roles - -The Pool is an ERC20 share token contract (`StvPool` / `StvStETHPool`) where users deposit ETH and receive STV shares. - -| Role | When applicable | Permissions | -| ---------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DEFAULT_ADMIN_ROLE` | always | Admin for pool roles and configuration. Assigned to the pool `TimelockController`. | -| `ALLOW_LIST_MANAGER_ROLE` | allowlist pools (non-strategy) | Manage the deposit allowlist: add/remove accounts (controls `DEPOSIT_ROLE`). | -| `DEPOSITS_PAUSE_ROLE` / `DEPOSITS_RESUME_ROLE` | always | Pause/resume ETH deposits into the pool.

**Pause**: Emergency Committee;
**Resume**: via timelock governance | -| `MINTING_PAUSE_ROLE` / `MINTING_RESUME_ROLE` | minting pools (`StvStETHPool`) | Pause/resume (w)stETH minting.

**Pause**: Emergency Committee;
**Resume**: via timelock governance | -| `LOSS_SOCIALIZER_ROLE` | minting pools (`StvStETHPool`) | Call `forceRebalanceAndSocializeLoss(...)` for undercollateralized accounts (typically used by an operator/keeper before emergency actions such as disconnect). | - -### Allowlist specifics - -- If allowlist is enabled for `StvPool` / `StvStETHPool`, the address is granted `ALLOW_LIST_MANAGER_ROLE`. -- For strategy pools the Strategy contract is added to the allowlist during deployment, and **users are expected to supply via the Strategy** (not via the Pool directly). - -## Withdrawal Queue roles - -Withdrawal Queue (`WithdrawalQueue`) manages withdrawal requests, finalization, and claiming. - -| Role | Permissions | Default assignment | -| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | -| `DEFAULT_ADMIN_ROLE` | Admin for queue roles. | `TimelockController` | -| `FINALIZE_ROLE` | Finalize withdrawals; set finalization gas cost coverage. | `nodeOperator` | -| `WITHDRAWALS_PAUSE_ROLE` / `WITHDRAWALS_RESUME_ROLE` | Pause/resume new withdrawal request submissions.

**Pause**: Emergency Committee;
**Resume**: via timelock governance | | -| `FINALIZE_PAUSE_ROLE` / `FINALIZE_RESUME_ROLE` | Pause/resume finalization.

**Pause**: Emergency Committee;
**Resume**: via timelock governance | | - -## Distributor roles - -Distributor (`Distributor`) is used for Merkle-based token distributions (e.g., incentives). - -| Role | Permissions | Default assignment | -| -------------------- | ----------------------------------------------------------------------------- | --------------------- | -| `DEFAULT_ADMIN_ROLE` | Admin for distributor roles. | `TimelockController` | -| `MANAGER_ROLE` | Manage distribution config: add supported tokens; update Merkle root and CID. | `nodeOperatorManager` | - -## How DeFi Wrapper wires stVault permissions - -During deployment, the Factory grants the DeFi Wrapper contracts the minimum required stVault `Dashboard` permissions: - -| Role | Default assignment | -| ---------------------------------------------------------- | ----------------------------------------------------- | -| `DEFAULT_ADMIN_ROLE` | TimelockController contract on the Dashboard contract | -| `FUND_ROLE` / `REBALANCE_ROLE` / `MINT_ROLE` / `BURN_ROLE` | StvPool/StvStETHPool contract | -| `WITHDRAW_ROLE` | Withdrawal Queue contract | -| `PAUSE_BEACON_CHAIN_DEPOSITS_ROLE` | Emergency Committee | diff --git a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/withdrawals.md b/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/withdrawals.md deleted file mode 100644 index b14ac138d..000000000 --- a/run-on-lido/stvaults-legacy/building-guides/pooled-staking-product/withdrawals.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 💸 Withdrawals operations - -This page explains how to operate withdrawals for a pooled staking product (DeFi Wrapper): how to monitor the Withdrawal Queue, ensure enough liquidity is available, and finalize requests. - -## How withdrawals work (high level) - -1. **Users place requests** (via the Pool UI / Pool contract). -2. Requests are subject to a **minimum delay** before they can be finalized. -3. **Node Operator monitors the queue** and ensures enough ETH liquidity is available on the vault balance by returning ETH from validators (e.g., exiting / triggering withdrawals) for the required amount. -4. A finalizer calls `WithdrawalQueue.finalize()` to **lock ETH** for claimable requests (and optionally rebalance stETH shares). -5. Users (or anyone on their behalf) call `claimWithdrawal()` to transfer locked ETH to the recipient. - -## Automation - -You can use CLI to automatically submit reports and finalize (if possible) withdrawals for the pool. Finalization requires private key of address holding `FINALIZE_ROLE`. This command will exit on errors and needs to be run with a process manager (missed reports will be checked on start) - -```bash -# Check --help for extra configuration and HTTP callbacks -yarn start defi-wrapper use-cases wrapper-operations w auto-report -``` - -## Monitor the Withdrawal Queue - -```bash -# Status of withdrawal queue for the pool, including finalization availability and CL ETH needed for withdrawals -yarn start defi-wrapper use-cases wrapper-operations r withdrawal-status -``` - -### In detail - -```bash -# -# Quick queue snapshot -# - -# Base info (includes addresses, flags, and parameters) -yarn start defi-wrapper contracts wq r info - -# How many requests are not finalized yet -yarn start defi-wrapper contracts wq r unfinalizedRequestsNumber - -# Total ETH amount in the queue that is still not finalized -yarn start defi-wrapper contracts wq r unfinal-assets - -# Optional: amounts expressed in STV / stETH shares -yarn start defi-wrapper contracts wq r unfinal-stv -yarn start defi-wrapper contracts wq r unfinalizedStethShares -``` - -#### Identify the “backlog” range - -```bash - -# Last request ever created -yarn start defi-wrapper contracts wq r last-request-id - -# Last request already finalized -yarn start defi-wrapper contracts wq r last-finalized-request-id -``` - -The unfinalized request IDs are typically in the range: - -- `lastFinalizedRequestId + 1 ... lastRequestId` - -#### Inspect a specific request - -```bash -# Status for a single request id -yarn start defi-wrapper contracts wq r w-status - -# How much ETH is claimable for a request (if finalized) -yarn start defi-wrapper contracts wq r get-claimable-ether -``` - -#### Check available vault balance - -```bash - -# ETH that is available for withdrawal (excludes staged balances for activations) -yarn start contracts vault r available-balance - -# How much ETH is staged for validator activations -yarn start contracts vault r staged-balance -``` - -## Ensure there is enough liquidity to finalize - -Finalization requires enough ETH to be available for withdrawals (and for gas cost coverage, see below). If `finalize` reverts, the usual cause is **insufficient available balance** on the underlying staking vault. - -### If liquidity is not enough: return ETH from validators - -Operationally, to satisfy withdrawals you need ETH back on the vault balance. Depending on your setup, this may involve: - -- **Triggering validator withdrawals** (with `TRIGGER_VALIDATOR_WITHDRAWAL_ROLE` - not assigned by default) -- **Exiting validators** - -CLI has Vault-level helpers for these operations: - -```bash -# Ask the node operator to exit validators (request is emitted; actual exits must be handled by the NO) -yarn start contracts vault w no-val-exit - -# Trigger EIP-7002 exits by the node operator -yarn start contracts vault w eject-validators - -# Trigger validator withdrawals -yarn start contracts vault w trigger-v-w -``` - -For role/permission boundaries between Vault Owner vs Node Operator actions, see [stVaults Roles and permissions](/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions). - -## Finalize requests - -Finalization is performed by an account with `FINALIZE_ROLE` on the Withdrawal Queue (in DeFi Wrapper deployments, this is typically the `nodeOperator`). - -```bash -yarn start defi-wrapper use-cases wrapper-operations w finalize-withdrawals -``` - -Options: - -- `--max-requests `: default 1000, finalize up to maxRequestCount requests in one transaction (the function stops earlier if it hits a limiting condition). -- `--gas-coverage-recipient `: defaults to tx sender, where the gas cost coverage (if any) is paid - -## After finalization - -Users are able to claim their assets for the finalized requests by calling `claimWithdrawal` or `claimWithdrawalBatch` on the `WithdrawalQueue` contract. - -## What is `gasCostCoverage` - -`gasCostCoverage` is a per-request ETH amount that can be paid out during finalization to compensate the finalizer for gas costs (bounded by the on-chain constant `MAX_GAS_COST_COVERAGE`). - -You can inspect the configuration via CLI: - -```bash -# Current configured per-request gas coverage (wei) -yarn start defi-wrapper contracts wq r getFinalizationGasCostCoverage - -# Maximum allowed coverage (wei) -yarn start defi-wrapper contracts wq r MAX_GAS_COST_COVERAGE -``` - -**How it’s applied** - -- During `finalize`, the contract accumulates total coverage across finalized requests and transfers it to `gasCostCoverageRecipient`. -- This coverage is accounted for when checking available balances, so higher coverage increases the ETH required to finalize the same set of requests. - -**How to change it** - -The on-chain method is `setFinalizationGasCostCoverage(uint256)`, which requires `FINALIZE_ROLE`. - -```bash -# Requires FINALIZE_ROLE for used account -yarn start defi-wrapper use-cases wrapper-operations w set-finalization-gas-cost-coverage -``` diff --git a/run-on-lido/stvaults-legacy/features-and-mechanics/exit-validators.md b/run-on-lido/stvaults-legacy/features-and-mechanics/exit-validators.md deleted file mode 100644 index 4772b3b56..000000000 --- a/run-on-lido/stvaults-legacy/features-and-mechanics/exit-validators.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -sidebar_position: 3 ---- - -# ⬇️ Exit Validators - -Different stVault participants have specific permissions to initiate validator exits or withdrawals from the Consensus Layer. - -## Node Operator - -A Node Operator can directly perform validator operations: - -- Exit a validator. -- Perform a **partial ETH withdrawal** from the validator. - -## Vault Owner - -A Vault Owner can do direct and indirect withdrawals: - -- Request a **validator exit** (the exit transaction is performed by the Node Operator) -- Trigger a **partial or full forced ETH withdrawal** from the validator: - - **0 ETH** — triggers a full validator exit. - - **Any positive amount** — keeps at least **32 ETH** on the validator balance. - -## stVaults Committee - -The stVaults Committee can trigger a **forced validator exit**, but only if the vault has outstanding **Obligations**: - -- **Health Factor < 100%**. -- **Unsettled Lido fees ≥ 1 ETH**. -- **Redemptions** (currently deactivated on Mainnet). - -## Lido DAO - -The DAO can also trigger a **forced validator exit**, but only if the vault has obligations: - -- **Health Factor < 100%**. -- **Unsettled Lido fees ≥ 1 ETH**. -- **Redemptions** — currently deactivated on Mainnet, but can be activated within the same DAO vote. \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/features-and-mechanics/index.md b/run-on-lido/stvaults-legacy/features-and-mechanics/index.md deleted file mode 100644 index 3e9b06081..000000000 --- a/run-on-lido/stvaults-legacy/features-and-mechanics/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 🔍 stVaults Features and Mechanics - -Core mechanics and configuration details for stVaults, including roles, permissions, and key parameters. - -## In this section - -- [Roles and permissions](./roles-and-permissions.md) -- [Parameters and metrics](./parameters-and-metrics.md) -- [Exit Validators](./exit-validators.md) diff --git a/run-on-lido/stvaults-legacy/features-and-mechanics/parameters-and-metrics.md b/run-on-lido/stvaults-legacy/features-and-mechanics/parameters-and-metrics.md deleted file mode 100644 index c11e3f1dc..000000000 --- a/run-on-lido/stvaults-legacy/features-and-mechanics/parameters-and-metrics.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -sidebar_position: 2 ---- - -# 📊 Parameters and metrics -## stVaults parameters - -### Reserve Ratio -Defines the amount of ETH that will be reserved as part of the collateral when the Vault Owner mints stETH in the stVault. stETH isn't minted for this amount. - -### Forced Rebalance Threshold -Defines the minimum allowed ratio of stETH Liability to Total Value. Exceeding this minimum threshold makes the vault subject to forced rebalancing. - -## stVaults metrics - -### Total Value -The total amount of ETH, consisting of ETH staked on validators plus ETH held in the vault balance. Rewards accrue to both and increase Total Value. - -### Not Staked stVault Balance -The amount of ETH held on the stVault Balance (Vault contract balance) and not deposited on validators, and therefore not used for earning rewards. - -### Staked on validators -The amount of ETH deposited on validators and used for earning rewards. - -### Total Lock -The total amount of ETH locked in the stVault due to a combination of reasons: fees obligations, collateral either for stETH liability or the connection to Lido Core, etc. - -### Collateral -The amount of ETH locked in the stVault, either to cover stETH liability under the Reserve Ratio or to maintain the connection to Lido Core (minimum 1 ETH). - -### Reserve -The amount of ETH that is reserved as part of the collateral when the Vault Owner mints stETH in the stVault. stETH isn't minted for this amount. - -### Minimal Reserve -The amount of ETH that is always reserved in the stVault regardless of the Total Value. Minimal Reserve = 1 ETH by default, and may be increased in response to a correlated slashing event according to the [Risk management framework](https://research.lido.fi/t/risk-assessment-framework-for-stvaults/9978/4). - -### stETH minting limit -Absolute maximum limit for the stETH minting capacity defined by the Tier the stVault belongs to. It can be changed by changing the Tier. - -### Total stETH minting capacity -The amount of stETH the Vault Owner can mint within the Reserve Ratio boundaries, considering a Minimal Reserve: - -``` -Total stETH minting capacity = -max - ( - 0, - Total Value - - Unsettled Fees - - max - ( - Minimal Reserve, - (Total Value - Unsettled Fees) * Reserve Ratio / 100% - ) - ) -``` - -Also, it can be limited by: -- stVault personal stETH minting limit; -- Tier remaining capacity; -- Node Operator remaining capacity; -- Total stVaults remaining capacity; -- Lido Core staking rate limits ([learn more](/guides/lido-tokens-integration-guide/#staking-rate-limits)). - - -### stETH Liability -The amount of stETH that the Vault Owner minted in the vault, backed by the ETH collateral. Increases daily due to the stETH rebase. - -### Remaining stETH minting capacity -The amount of stETH remaining mintable in the vault, based on the current Total stETH minting capacity and stETH Liability. - -### Utilization Ratio -The share of the stETH minting capacity currently utilized by the Vault Owner. - -### Health Factor -The Health Factor demonstrates the economic state of the stVault. It shows how the stETH Liability is backed by the Total Value. - -$$ -Health Factor = \frac{Total Value \times (1 - Forced Rebalance Threshold)}{stETH Liability} -$$ - -### Locked by fees obligations (unsettled fees) -The amount of ETH locked in the vault due to the undisbursed Node Operator fee and unsettled Lido fees. - -### Pending unlock -The amount of ETH eligible for unlocking after stETH is repaid, but still pending confirmation from the next Oracle report. - -### Available to withdraw -The amount of ETH that is available to withdraw from the stVault Balance. Constrained by the total locked ETH on the stVault and the amount of ETH deposited on validators. - -### Undisbursed Node Operator fee -The amount of accumulated but not yet disbursed Node Operator Fee. This amount of ETH increases the total locked ETH. - -### Unsettled Lido fees -The amount of accumulated but not yet settled Lido fees. This amount of ETH increases the total locked ETH. - -The Lido fee consists of the following components and is calculated daily: - -- Infrastructure fee -- Liquidity fee -- Reservation liquidity fee - -### Gross staking rewards -The amount of ETH earned by validators. - -### Node Operator rewards -The amount of ETH payable to the Node Operator as a Node Operator fee. - -### Net staking rewards -The amount of staking rewards remaining after deduction of the Node Operator fee and Lido fees. - -### Gross staking APR -The amount of rewards earned by the validators expressed as a percentage of the stVault Total Value, before fee deductions. - -### Net staking APR -Estimated yearly returns from staking in the vault, after fees deductions but without taking into account stETH Liability growth due to stETH rebase. - -### stVault bottom line -The final amount of rewards earned by the Vault Owner within the vault perimeter. - -Calculated as the difference between the Net Staking Rewards and the stETH Liability growth: - -stVault bottom line = Net staking rewards - stETH rebase - -### Carry Spread -Estimated yearly returns from staking in the vault, after deduction of fees and stETH Liability growth due to stETH rebase. - -Carry spread indicates the Health Factor trend: a positive spread raises the Health Factor, while a negative spread lowers it. - -### Lido infrastructure fee -The fee that Lido charges for using the stVaults infrastructure. Calculated from the stVault Total Value: - -Infrastructure Fee = Total Value × Lido Core APR × Infrastructure Fee Percentage - -### Lido liquidity fee -The fee that Lido charges for actual liquidity usage. Calculated from the stETH Liability: - -Liquidity Fee = stETH Liability × Lido Core APR × Liquidity Fee Percentage - -### Lido reservation liquidity fee -The fee that Lido charges for liquidity on demand. Calculated from the stETH minting capacity: - -Reservation Liquidity Fee = stETH minting capacity × Lido Core APR × Reservation Liquidity Fee Percentage - -### stETH rebase -The change in stETH amount that occurs because stETH is a rebasing token. The rebase amount is based on the stETH APR. - -### Node Operator fee -The share of Gross staking rewards that the Node Operator charges for providing validation services. - -## Rebalancing unhealthy stVault - -### ETH to supply -The amount of ETH recommended to supply to the vault to compensate for the ETH deficit and return the Utilization Ratio to 100%. - -### stETH to repay -The amount of stETH recommended to repay to the vault to compensate for the ETH deficit and return the Utilization Ratio to 100%. - -### ETH to rebalance -The amount of ETH on the vault balance recommended to rebalance to compensate for the ETH deficit and return the Utilization Ratio to 100%. - -Rebalance is a mechanism that sends available ETH from the stVault balance to Lido Core, receiving stETH at a 1:1 ratio, and repaying the received stETH back to the stVault so that the Utilization Ratio returns to 100%. - -The amount of ETH for rebalancing to bring the Utilization Ratio to 100% is pre-calculated by the system or can be calculated using the formula: - -ETH for rebalance = (stETH Liability − (1 − RR) × Total Value) / RR - -## Lido Core reference metrics - -### stETH APR -Estimated total yearly returns from staking in the Lido Core protocol. - -### Lido Core APR -Gross annualized rewards earned by validators in the Lido Core protocol. - -### Node Operator fee at Lido Core -The average share of staking rewards that Node Operators of the Lido Core protocol receive for providing validation services. diff --git a/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions.md b/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions.md deleted file mode 100644 index 9890aebd9..000000000 --- a/run-on-lido/stvaults-legacy/features-and-mechanics/roles-and-permissions.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 🔐 Roles and permissions -## Vault contract role - -**Node Operator** provides validation service for the vault: handles depositing ETH from the vault balance to validators and exiting validators if necessary. Address of the Node Operator can’t be changed after the vault is created. - -:::info -**The Node Operator address** is registered in the **Operator Grid** contract as the primary identifier of the Node Operator. Tiers with defined **Reserve Ratios** and **stETH minting limits** are assigned to this address according to the obtained Category. - -This address is also used to perform key operations in stVaults from the Node Operator’s perspective and must be set up as a **multisig** for security reasons. -::: - -### Node Operator's non-delegable permissions -| Operation | -| -------- | -| Deposit ETH from Staking Vault to validators using Predeposit Guarantee contract. | - -## Dashboard contract roles and permissions - -1. **Vault Owner** [Dashboard contract role DEFAULT_ADMIN (VAULT_OWNER)] is one of the two admin roles for the stVault. It allows managing permissions and changing key vault parameters from the Vault Owner (Staker) perspective. Multiple addresses are supported. - -2. **Node Operator Manager** [Dashboard contract role NODE_OPERATOR_MANAGER] is another of the two admin roles for the stVault. It allows managing permissions and changing key vault parameters from the Node Operator perspective. Multiple addresses are supported. - -**Vault Owner** and **Node Operator Manager** addresses have permissions for all actions within their respective scopes in stVaults. They can also delegate specific permissions (sub-roles) to other addresses. - -### Permissionless operations - -| Permission | Operation | -| -------- | -------- | -|Permissionless | Disburse Node Operator fees. | - -### Vault Owner's non-delegable permissions -These operations are available only to addresses with the admin role. -| Permission | Operation | -| -------- | -------- | -|DEFAULT_ADMIN_ROLE | Grant/Remove role or permission, including own role DEFAULT_ADMIN (VAULT_OWNER). | -|| Confirm the transfer of the StakingVault ownership (Abandon Dashboard, Connect to VaultHub, Reconnect to VaultHub). | -|| Propose and confirm changing NO fee by Multi-roles confirmation. | -|| Propose and confirm changing the Confirmation Expiry parameter by Multi-roles confirmation. | -|| Propose and confirm AccruedRewardsAdjustment: Marks directly transferred ETH as funded (supplied) so that these assets wouldn't be considered as rewards. | - - -### Vault Owner's delegatable permissions (sub-roles) -:::info -By default, if no override admin role is set, the Vault Owner can perform all the actions described below. -::: -| Permission | Operation | -| -------- | -------- | -| FUND_ROLE | Supply (fund) ETH to the stVault. | -| WITHDRAW_ROLE | Withdraw ETH from the stVault Balance | -| MINT_ROLE | Mint stETH in a boundaries of stETH minting capacity | -| BURN_ROLE | Repay (burn) previously minted stETH to decrease stETH Liability | -| REBALANCE_ROLE | Perform voluntary rebalance | -| PAUSE_BEACON_CHAIN_DEPOSITS_ROLE | Pause ETH deposits to Beacon Chain | -| RESUME_BEACON_CHAIN_DEPOSITS_ROLE | Resume ETH deposits to Beacon Chain | -| REQUEST_VALIDATOR_EXIT_ROLE | Ask Node Operator to exit validator and return ETH to stVault Balance | -| TRIGGER_VALIDATOR_WITHDRAWAL_ROLE | Force fully or partially withdraw ETH from validator | -| VOLUNTARY_DISCONNECT_ROLE | Disconnect from Lido VaultHub (disables minting stETH, stops paying fees to Lido, distributes Node Operator fee) | -| VAULT_CONFIGURATION_ROLE | — Request to OperatorGrid to change the vault tier (specify new tier) | -| | — Request to OperatorGrid to change the sync with tier params | -| | — Request to OperatorGrid to update share limit on the vault | -| | — Accept new tier on connection to the VaultHub | -| COLLECT_VAULT_ERC20_ROLE | Allows recovery of ERC20 tokens wrongly transferred to the Dashboard contract or claiming of incentives transferred to the vault address as ERC20 tokens | - - -### Node Operator Manager's non-delegable permissions (sub-roles) -| Permission | Operation | -| -------- | -------- | -|NODE_OPERATOR_MANAGER_ROLE| Grant/Remove role or permission, including own role NODE_OPERATOR_MANAGER. | -|| Propose and confirm changing NO fee by Multi-roles confirmation. | -|| Propose and confirm changing Confirmation Expiry parameter by Multi-roles confirmation. | -|| Propose and confirm AccruedRewardsAdjustment: Marks directly transferred ETH as funded (supplied) so that these assets wouldn't be considered as rewards. | -|| Set NO fee recipient address. | - -### Node Operator Manager's delegatable permissions (sub-roles) -:::info -By default, if no override admin role is set, the Node Operator Manager can perform all the actions described below. -::: - -| Permission | Operation | -| -------- | -------- | -| NODE_OPERATOR_UNGUARANTEED_DEPOSIT_ROLE | Withdraw ETH from the vault and deposit directly to provided validators, bypassing the default PDG process | -| NODE_OPERATOR_PROVE_UNKNOWN_VALIDATOR_ROLE | Prove unknown validators through PDG | -| NODE_OPERATOR_FEE_EXEMPT_ROLE | Add a fee exemption to exclude this value from the Node Operator fee base. The exemption works by increasing the settled growth, effectively treating the exempted amount as if fees were already paid on it | - - -## Predeposit guarantee contract roles and permissions - -### Permissionless operations -| Permission | Operation | -| -------- | -------- | -|Permissionless | Provide Merkle Proof of validator existence on CL (positive). | -| | Provide Merkle Proof of invalid validator existence on CL (negative) and compensate the staking vault. | - -### Predeposit guarantee contract configurable permissions - -| Role | Operation | -| -------- | -------- | -| Node Operator | Set Node Operator’s guarantor. Set Node Operator’s depositor. | -| Vault Owner | Prove unknown validator. | -| Guarantor | Top up Node Operator’s guarantor bond. Withdraw Node Operator’s guarantor bond. Claim bond refund. | -| Depositor | Pre-deposit validators to Beacon Chain. Deposit validators to Beacon Chain. | diff --git a/run-on-lido/stvaults-legacy/index.md b/run-on-lido/stvaults-legacy/index.md deleted file mode 100644 index 3fa306ed2..000000000 --- a/run-on-lido/stvaults-legacy/index.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -sidebar_position: 2 ---- - -# [LEGACY] stVaults Documentation Center - - -## 🛠️ Building Guides - -The stVaults platform enables the creation of staking products tailored to different target audiences with diverse needs. These two comprehensive guides provide detailed instructions on how to create any product powered by stVaults. - -| Staking Product to build | Its Value Proposition | Its Segments | -|---------------------------------------------------------------------------------------| -------- | -------- | -| [Basic stVault with optional liquidity](./building-guides/basic-stvault.md) | A competitive alternative to native staking: users stake with the same Node Operator while gaining optional liquidity through stETH. | Institutional stakers, large individual stakers (32+ ETH), funds, treasuries, builders, integrators, liquidity providers. | -| [End-user staking product by DeFi Wrapper](./building-guides/pooled-staking-product/) | A DeFi-wrapped stVault with pooling, liquidity, automated yield-boosting strategy, and white-labeled staking UI – all in one customizable no-code/low-code solution. | Retail stakers (<32 ETH), APR-maximizers, institutional stakers seeking a simple staking UI. | - -:::info -Have your own custom product in mind? [Contact us](https://tally.so/r/mVrkZa)! -::: - -## 📚 stVaults Resources - -### Essentials - -1. [📘 **Lido V3 Technical Paper**](/run-on-lido/stvaults/concepts-and-reference/lido-v3-whitepaper.mdx) — Complete technical specification with PDF preview -2. [[Forum post] Risk assessment framework](https://research.lido.fi/t/risk-assessment-framework-for-stvaults/9978/4) -3. [[Forum post] Fees structure and charging logic](https://research.lido.fi/t/default-risk-assessment-framework-and-fees-parameters-for-lido-v3-stvaults/10504) - -### 🔧 Tools - -1. [stVaults Web UI on Hoodi Testnet](https://stvaults-hoodi.testnet.fi/) -2. [stVaults Web UI on Mainnet](https://stvaults.lido.fi/) -3. [Command-line interface (CLI)](https://lidofinance.github.io/lido-staking-vault-cli/) -4. [stVaults product economy calculator](https://docs.google.com/spreadsheets/d/1Zwixmdq93Pe_jXeuKZTMj5yY_b7HEh8ua5OY_6icxT8/edit?usp=sharing) - -### 📝 Operational and Management Guides - -1. [Health Monitoring guide](./operational-and-management-guides/health-monitoring-guide.md) -2. [Health Emergency guide](./operational-and-management-guides/health-emergency-guide.md) -3. [stVaults Economy Examples](./operational-and-management-guides/stvaults-economy-examples.mdx) -4. [Voluntary Rebalancing and Vault Closure](./operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md) -5. [Applying Oracle Reports](./operational-and-management-guides/applying-report-guide.md) -6. [stVault Disconnect Guide](./operational-and-management-guides/stvault-disconnect-guide.md) -7. [Become an Identified Node Operator and get tiers, or request changes](./operational-and-management-guides/node-operators-identification.md) - -### 🔍 stVaults Features and Mechanics - -1. [stVaults Roles](./features-and-mechanics/roles-and-permissions.md) -2. [stVaults Parameters and Metrics](./features-and-mechanics/parameters-and-metrics.md) -3. [Exit Validators](./features-and-mechanics/exit-validators.md) - -### 📚 Tech Documentation - -1. [stVaults Integration Overview](./tech-documentation/integration-overview.md) -2. [stVaults Technical Design](./tech-documentation/tech-design.md) -3. [DeFi Wrapper Technical Design](https://hackmd.io/@lido/lido-v3-wrapper-design) -4. [Deployed Testnet Contracts](../../deployed-contracts/hoodi/) -5. [Migrate validators to stVault through consolidation](./tech-documentation/consolidation.md) -6. [Deposit validators through Predeposit Guarantee](./tech-documentation/pdg.md) -7. [stVaults contracts reference](/contracts/vault-hub) - -### 🏛️ Qualified Custodians Supporting stVaults - -1. [Overview of qualified custodians supporting stVaults](./qualified-custodians/index.md) -2. [Fireblocks user guide](./qualified-custodians/fireblocks.md) -3. [Copper user guide](./qualified-custodians/copper.md) -4. [Cactus Custody user guide](./qualified-custodians/cactus.md) - -:::tip 📣 **Leave feedback** -Trying to integrate with Lido V3 and stVaults? -Please share your thoughts through **[the short form](https://tally.so/r/3X9vYe)**. -::: diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/applying-report-guide.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/applying-report-guide.md deleted file mode 100644 index 43c66fd79..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/applying-report-guide.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -sidebar_position: 5 ---- - -# 📊 Applying Oracle Reports - -Before minting stETH or performing other operations that depend on current vault state, the protocol needs to ensure that you are working with the latest available data. [LazyOracle](/contracts/lazy-oracle) allows anyone to apply the latest report to a specific vault on demand. - -## Why apply a fresh report? - -Your stVault's state (total value, mintable stETH capacity, health factor) is updated through oracle reports. These reports are published periodically, but applying them to your specific vault is a separate, permissionless action. Fresh data is required for: - -- minting stETH, -- withdrawing ETH, -- rebalancing, -- changing tiers, -- resuming beacon deposits, -- partial validator withdrawals, -- settling Lido fees, -- disconnecting the vault. - -:::info -Many vault operations (except funding and burning shares) will revert if the report is stale. When you are not sure why your operation reverts, apply a fresh report first. -::: - -## How it works - -1. The [AccountingOracle](/contracts/accounting-oracle) publishes a Merkle tree root containing data for all vaults -2. You get your vault's data and proof from IPFS using the published CID -3. You submit the data and proof to the [LazyOracle](/contracts/lazy-oracle) contract -4. [LazyOracle](/contracts/lazy-oracle) verifies the proof and updates your vault's state in [VaultHub](/contracts/vault-hub). - -This is a **permissionless operation** — anyone can apply a report to any vault. - -
- using stVaults Web UI - - The Web UI automatically applies fresh reports when needed before executing operations like minting, repaying, or tier changes. No manual action is required in most cases. - - The report status is displayed at the top of the vault overview page, showing the last update timestamp and a link to view the oracle report on IPFS. - - ![Oracle report](/img/stvaults/guide-basic-stvault/report_uptodate.png) - - In certain situations (such as when deposits are restricted due to accumulated fees, or when the vault is pending disconnection), an "Apply the latest Oracle report" button will appear in the relevant warning banner if a newer report is available. - -
-
- using Command-line Interface - - Apply the latest report to your vault: - - ```bash - yarn start report w submit -v - ``` - The CLI automatically: - - - fetches the latest report CID from LazyOracle, - - retrieves the Merkle tree from IPFS, - - generates the proof for your vault, - - submits the transaction. - -
-
- using Etherscan UI - - Applying a report via Etherscan requires manually fetching the proof data from IPFS. For most users, the CLI or Web UI is recommended. - - 1. Query the **LazyOracle** contract's `latestReportData()` method to get the current `reportCid`. - 2. Fetch the Merkle tree JSON from IPFS using the CID: `https://ipfs.io/ipfs/` - 3. Locate your vault's entry in the tree and copy the data. - 4. Open **Etherscan** and navigate to the **LazyOracle** contract by its address (available in the stVaults contract addresses list, see [Basic stVault with optional liquidity: Environments](../building-guides/basic-stvault#environments)). - 5. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. - 6. Open the **Contract** tab → **Write as Proxy**. - 7. Click **Connect to Web3** and connect your wallet in the dialog window. - 8. Find the `updateVaultData` method in the list, fill out the fields with the data from IPFS, and click **Write**. - 9. Sign the transaction in your wallet. - 10. Click **View your transaction** and wait for it to be executed. - -
- -## Checking report freshness - -You can check when your vault's report was last updated: - -
- using Command-line Interface - - ```bash - yarn start vo r info -v - ``` - This displays the vault's current metrics including the last report timestamp. - -
-
- using Etherscan UI - - 1. Open **Etherscan** and navigate to the **LazyOracle** contract. - 2. Go to the **Contract** tab → **Read as Proxy**. - 3. Find the `latestReportTimestamp` method and click **Query** to see when the latest report was published. - 4. Find the `vaultInfo` method, enter your vault address, and click **Query** to see your vault's current on-chain metrics. - -
- -:::info -You can use any online UNIX timestamp converter to get the human readable datetime format. -::: diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/health-emergency-guide.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/health-emergency-guide.md deleted file mode 100644 index d7ecb0fd6..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/health-emergency-guide.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 🚨 Health Emergency Guide - -## TLDR - -The stVault has two key parameters: **Reserve Ratio (RR)** and **Force Rebalance Threshold (FRT)**. - -- **RR (e.g., 10%)** limits how much stETH can be minted from ETH in the stVault. -- **FRT (e.g., 9%)** triggers a forced rebalance if the stVault’s reserve drops too low. - -When slashing events (or low performance) reduce the stVault's total value, its **reserve factor** can fall below RR and FRT, making it **unhealthy** and requiring corrective action. - -There are **three ways to restore stVault Health**: - -1. **Burn stETH** – Restores the reserve ratio without changing total value; keeps rewards unchanged but reduces external earnings. -2. **Add ETH** – Increases stVault value and future rewards; requires adding extra capital. -3. **Rebalance / Wait for Forced Rebalancing** – Moves ETH to Lido Core and writes off equivalent debt; least recommended, as it lowers stVault total value and reduces future rewards. - -## Definitions - -- **Reserve Ratio (RR)** limits minting — this means that users will be able to mint up to 90% of stETH out of ETH they put into the stVault. However, falling below RR doesn't force an immediate correction. -- **Force Rebalance Threshold (FRT)** defines when forced rebalancing is *allowed to* happen. A rebalancing may happen to improve the stVault's health and prevent stVault insolvency. It is always lower than RR: FRT < RR (e.g., 9% if RR = 10%). -- **Health Factor (HF)** is a metric calculated using the following formula: Health Factor = Total Value × (1 − FRT) / Minted stETH - - We have following levels of HF in stVaults Web UI: - - - HF ≥ 125% - Healthy stVault - - 125% > HF ≥ 105% - Healthy stVault, and moderate risk of rebalancing - - 105% > HF ≥ 100% - Healthy stVault, but too close to Unhealthy stVault, critical risk of rebalancing - - 100% > HF - Unhealthy stVault - -- **Utilization Ratio (UR)** is a metric that shows how much stETH is minted out of Total stETH Minting Capacity: Utilization Ratio = (stETH Liability / Total stETH Minting Capacity) × 100% - -## Explanatory scenario: - -### stVault - -- RR = 10% -- FRT = 9% -- Vault Owner deposits 100 ETH → mints 90 stETH (up to max mintable) -- Utilization ratio = 90 / 90 = 100% -- Health Factor = 100 × (100% − 9%) / 90 = 101.11% - - - -### Step 1: Slashing - -Validator gets **slashed by 1 ETH** → total backing = 99 ETH: -- Total Value = 99 ETH -- Reserve: 99 − 90 = 9 ETH -- Reserve factor is 9 / 99 = 9.09% → below 10% RR but above 9% FRT -- Utilization ratio = 90 / (99 × 0.9) = 101% -- Health Factor = 99 × (100% − 9%) / 90 = 100.1% - - - - -**The stVault is still healthy, but is really close to rebalancing** (Reserve factor is below RR). However, nothing happens yet: the user can't mint more stETH, but forced rebalancing will not happen if the ratio stops decreasing. - -### Step 2: More slashing -Validator **slashing continues by an additional 0.5 ETH** → total backing = 98.5 ETH: -- Total Value = 98.5 ETH -- Reserve: 98.5 − 90 = 8.5 ETH -- Reserve factor is 8.5 / 98.5 = 8.63% → **below 10% RR** and **below 9% FRT** -- Utilization ratio = 90 / (98.5 × 0.9) = 101.5% -- Health Factor = 98.5 × (100% − 9%) / 90 = 99.6% - - - -### Step 3: Healing stVault - -**The stVault is unhealthy now and action is required to restore its health.** - -There are a few ways to restore health: - -#### 1. Burn stETH - -User needs to burn 1.35 stETH, so that the stVault has: - -- Total Value: 98.5 ETH -- Debt: 90 − 1.35 = 88.65 stETH minted -- Reserve = 98.5 − 88.65 = 9.85 -- Reserve factor 9.85 / 98.5 = 10% → equals 10% RR and above 9% FRT -- Utilization ratio = 88.65 / (98.5 × 0.9) = 100% -- Health Factor = 98.5 × (100% − 9%) / 88.65 = 101.11% - - - -**Pros:** -- Should this method be selected to restore stVault health, the user's future rewards from the stVault will remain unaffected, since the Total Value remains unchanged. - -**Cons:** -- The user is required to burn stETH, potentially resulting in a decrease in earnings outside the stVault. -#### 2. Add ETH to the stVault - -User needs to top up the stVault balance (Total Value) by 1.5 ETH: - -- Total Value: 98.5 + 1.5 = 100 ETH -- Debt: 90 stETH minted -- Reserve = 100 − 90 = 10 -- Reserve factor 10 / 100 = 10% → equals 10% RR and above 9% FRT -- Utilization ratio = 90 / (100 × 0.9) = 100% -- Health Factor = 100 × (100% − 9%) / 90 = 101.11% - - - -**Pros:** -- If this method is selected to restore stVault health, the user's future rewards from the stVault will increase, as the Total Value is higher. -- The user is not required to burn stETH, so their potential earnings outside the stVault remain unaffected. - -**Cons:** -- The user needs to provide additional capital to the stVault. - -#### 3. Rebalance or do nothing and wait for forced rebalancing - -⚖️ Rebalance is moving enough ETH from the stVault to Lido Core, writing off the same stETH debt 1:1 (not burned, now backed by Core). - -For this example, the required amount to be moved is 13.5 ETH: - -- Total Value: 98.5 − 13.5 = 85 ETH -- Debt: 90 − 13.5 = 76.5 stETH minted -- Reserve = 85 − 76.5 = 8.5 -- Reserve factor 8.5 / 85 = 10% → equals 10% RR and above 9% FRT -- Utilization ratio = 76.5 / (85 × 0.9) = 100% -- Health Factor = 85 × (100% − 9%) / 76.5 = 101.11% - - - -This is the least recommended method for restoring stVault health. - -**Pros:** -- The user is not required to burn stETH, so their potential earnings outside the stVault remain unaffected. - -**Cons:** -- The user's future rewards from the stVault will be significantly reduced due to a decrease in the stVault's Total Value — from 98.5 ETH to 85 ETH (approximately −14%). - -#### Let’s sum up: - -In this scenario, there are three possible ways to restore the stVault’s health: - -1. Repay 1.35 stETH -2. Supply 1.5 ETH -3. Rebalance 13.50 ETH - -All three methods ultimately bring the stVault’s Utilization Ratio back to **100%**. However there are pros and cons for each of the methods. diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/health-monitoring-guide.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/health-monitoring-guide.md deleted file mode 100644 index 98f247061..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/health-monitoring-guide.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -sidebar_position: 2 ---- - -# 🩺 Health Monitoring Guide - -## Definitions - -- **Reserve Ratio (RR)** limits minting — this means that users will be able to mint up to 90% of stETH out of ETH they put into the stVault. However, falling below RR doesn't force an immediate correction. -- **Utilization Ratio (UR)** is a metric that shows how much stETH is minted out of Total stETH Minting Capacity: Utilization Ratio = (stETH Liability / Total stETH Minting Capacity) × 100% - -## TLDR - -Regularly monitoring **Health factor**, **Carry Spread**, **Net staking APR**, and **stETH Liability / Utilization ratio** is a good operational practice for vault owners. - -Keeping these metrics within safe ranges allows you to: - -- Detect early signals that the vault economics are deteriorating. -- React before the Health factor approaches 100% or Utilization ratio reaches 100%. -- Reduce the likelihood that the vault will enter a state where [forced rebalancing or other emergency actions become necessary](./health-emergency-guide.md). - -Consistent observation of these indicators helps minimize the risk that vault health degrades to unacceptable levels and supports the long-term stability of the stVault. - -## Monitoring stVaults health in the UI - -The **Vault overview** screen provides a quick view of the economic state of a specific stVault. - -![stVaults UI: Overview screen](/img/stvaults/health/health-overview.png) - -From here you can drill down into the key metrics that determine vault health: - -- **Health factor** -- **Net staking APR** -- **stETH Liability / Utilization ratio** - -This section explains what each metric means, where to find it in the UI, and what to pay attention to when monitoring your vault. - -### Health factor - -**Definition:** Health Factor (HF) is a metric calculated using the following formula: Health Factor = Total Value × (1 − FRT) / Minted stETH - -**Health factor** shows how well the stETH Liability is collateralized by the Total value of the vault. - -It is the primary indicator of the vault’s overall health. - -- As a rule, the Health factor **should always remain above 100%**. -- When the Health factor moves closer to 100%, the vault becomes riskier and may approach the forced rebalancing zone. -- If the Health factor falls below 100%, the vault becomes subject to [**forced rebalancing**](./health-emergency-guide.md). - -![stVaults UI: Health Factor](/img/stvaults/health/health-hf.png) - -In the Health factor details view you can also see **Carry Spread**. - -> Carry Spread — Estimated yearly returns from staking in the vault, after deductions of fees and stETH Liability growth due to stETH rebase. -> - -Carry Spread shows whether the vault economics are improving or deteriorating over time: - -- **Positive Carry Spread** - - Expected yearly return is positive after accounting for fees and Liability growth. - - All else equal, this supports **improving** or **stable** Health factor. -- **Negative Carry Spread** - - Expected yearly return is not sufficient to cover fees and Liability growth. - - Over time this tends to **erode** the Health factor and push it closer to 100%. - -If the Carry Spread turns negative or the Health factor trends down toward 100%, you should treat this as an early warning and consider taking actions to improve the vault’s economics. - -If the Health Factor of the vault drops below 100%, please refer to the [stVaults Health Emergency Guide](./health-emergency-guide.md). - -### Net staking APR - -**Net staking APR** shows the estimated yearly return from staking in the vault **after all protocol and node operator fees**, but **without** taking into account stETH Liability growth due to the daily stETH rebase. - -![stVaults UI: Net Staking APR](/img/stvaults/health/health-net-apr.png) - -This metric should be monitored relative to the **stETH APR**: - -- If **Net staking APR is higher than stETH APR** - - The vault is expected to outperform plain stETH staking before Liability growth. - - This is generally a **healthy** situation. -- If **Net staking APR is lower than stETH APR** - - The vault underperforms plain stETH on a fee-adjusted basis. - - This is a signal to **pay attention**: together with Carry Spread and the Health factor it may indicate that the vault configuration or performance needs to be reviewed. - -Persistent underperformance (Net staking APR < stETH APR) can contribute to a negative Carry Spread over time and, consequently, to a deterioration in the Health factor. - -### stETH liability and Utilization ratio - -**stETH Liability** is the amount of stETH that the vault owner has minted in the vault, backed by the ETH collateral. - -This value **increases daily** because of the stETH rebase. - -![stVaults UI: stETH Liability](/img/stvaults/health/health-steth-liability.png) - -In the stETH Liability details view you can also see: - -- **Total stETH minting capacity** (constrained by the Reserve Ratio) -- **Reserve Ratio (RR)** -- **Forced Rebalance Threshold (FRT)** -- **Utilization ratio** - -The key condition to monitor is that the vault’s Liability remains safely within its capacity: - -- stETH Liability should **not exceed** the allowed capacity defined by the Reserve Ratio / Forced Rebalance Threshold. -- In practice, this is equivalent to keeping the **Utilization ratio below 100%**. - -When **Utilization ratio approaches 100%**: - -- There is little remaining capacity to mint additional stETH. -- The vault comes closer to the boundary where forced rebalancing may be triggered. - -If Utilization reaches or exceeds 100%, the vault is effectively at or above its intended Liability limit and may enter the forced rebalancing zone. In this situation, the Vault Owner should promptly review their position and take corrective actions as described in the [stVaults Health Emergency Guide](./health-emergency-guide.md). diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/index.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/index.md deleted file mode 100644 index e067dcec9..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 📝 Operational and Management Guides - -Day-to-day guidance for running and maintaining stVaults safely, including health checks, emergency response, operator identification, and rollout notes. - -## In this section - -- [Health Monitoring Guide](./health-monitoring-guide.md) -- [Health Emergency Guide](./health-emergency-guide.md) -- [stVaults Economy Examples](./stvaults-economy-examples.mdx) -- [Voluntary Rebalancing and Vault Closure](./voluntary-rebalancing-and-vault-closure.md) -- [Applying Oracle Reports](./applying-report-guide.md) -- [stVault Disconnect Guide](./stvault-disconnect-guide.md) -- [Become an Identified Node Operator and get tiers, or request changes](./node-operators-identification.md) diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/node-operators-identification.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/node-operators-identification.md deleted file mode 100644 index 0a7534e8b..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/node-operators-identification.md +++ /dev/null @@ -1,359 +0,0 @@ ---- -sidebar_position: 7 ---- - -# 📝 Identified Node Operators - -This guide describes how to become an Identified Node Operator for stVaults and qualify for category-based tiers with specific Reserve Ratio & stETH minting limits. - -## Why become Identified - -- **stVaults are permissionless**, meaning **anyone can create and run an stVault**. However, if the stVault is created by an _unidentified_ Node Operator, it will be assigned to the _Default tier_ with a Reserve Ratio = **50%**. During the [V3 secure rollout](https://research.lido.fi/t/lido-v3-design-implementation-proposal/10665#p-22926-rollout-plan-9), stETH minting in the _Default tier_ will be restricted in the first two phases, which will be lifted later during “Phase 3: Permissionless Mode”. -- **Better economics vs. permissionless defaults.** The risk framework for V3 sets default RR and caps, and allows improved terms for identified Node Operators. The default terms are: **Unidentified = 50% RR**, **Identified ≈ 3–5% RR** (illustrative; final terms are case-by-case). -- **A clear governance path** exists to approve non-default terms and monitor performance via the **[stVaults Committee](https://research.lido.fi/t/stvaults-committee-proposal/10608)**. - ---- - -## The category → tiers model - -- **Node Operators are placed into a Category** that reflects combined operational, decentralization, and business factors (Basic identified, stVaults Professional Operator, stVaults Professional Trusted Operator). -- **Each category contains multiple tiers.** **A tier** is a specific **minting configuration** that defines the **Reserve Ratio (RR)**, **stETH Minting Limit (cap)**, and corresponding **Lido fees**. Operators receive a **tiers grid** (Tier 1…N) within their category; higher tiers increase the allowed minting cap but decrease the Reserve Ratio. -- Within the assigned category, **one Node Operator can hold multiple tiers** that the stVaults Committee can set or change based on the Node Operator’s requests, performance, slashing events, or market circumstances in accordance with the stVaults Risk Framework. -- Categories **Basic**, **stVaults Professional Operator**, and **DVT** can be granted to a Node Operator or DVT cluster upon request during the initial identification process. However, the **stVaults Professional Trusted Operator** category can only be awarded after three months of successful validation and proof of a significant amount of prospective funds to be acquired. - -### Categories and tiers - -#### Default Tier for Unidentified Node Operators (permissionless) - -This is a common tier shared by all stVaults operated by Unidentified Node Operators, meaning a single stETH minting limit applies to all stVaults within this tier. -| Reserve Ratio | Tier stETH limit | -| --- | --- | -| 50% | 500,000 stETH | - -#### Categories and Tiers for Identified Node Operators - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BasicstVaults Professional OperatorstVaults Professional Trusted OperatorDVT cluster
Tier NumberReserve RatioTier stETH limitReserve RatioTier stETH limitReserve RatioTier stETH limitReserve RatioTier stETH limit
15%47,500 stETH3.50%48,250 stETH2.50%48,750 stETH2%49,000 stETH
26%47,000 stETH4%48,000 stETH3%48,500 stETH2%49,000 stETH
39%182,000 stETH6%188,000 stETH4%192,000 stETH2%196,000 stETH
414%258,000 stETH10%270,000 stETH6.50%280,500 stETH3%291,000 stETH
520%320,000 stETH14.50%342,000 stETH10%360,000 stETH4%384,000 stETH
Total854,500 stETH896,250 stETH929,750 stETH969,000 stETH
- -## Category criteria - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CategoryUnidentified (permissionless)BasicstVaults Professional OperatorstVaults Professional Trusted OperatorDVT cluster
KYB(C)Not requiredRequiredRequiredRequiredRequired for each independent Node Operator in the Cluster
Infra requirements-BasicStrongStrongDVT cluster with 4+ independent Identified Node Operators
Operations Requirements-BasicStrongStrongUse DKG to generate keys
Business case (amount of ETH to be acquired)--Large amount of ETHSignificant amount of ETH-
Time constraints---3+ months of successful validation as an stVaults Professional Operator-
- -## **End-to-end process to become an Identified Node Operator or DVT Cluster** - -### Individual Node Operators identification and assessment - -1. **Public Identification Request on Lido Research Forum** - - Post your baseline request and summary on the Lido Research Forum – it is the formal trigger for consideration to be moved from _Unidentified_ to _Identified_. - - 🔗 [Lido Research Forum](https://research.lido.fi/c/node-operators/stvaults-identification/24) - - What information to provide: - - - Who you are; **request** (become Identified; apply for an advanced Category; apply for a Category change; any non-default requests). - - **[Concise] Business case**: ETH you can acquire — scales/market size, user segments, channels, partners, timelines, fee policy. - - **[Concise] Ops & decentralization**: client mix/versions, infra footprint, geo/jurisdiction diversity, MEV posture. - - **Links**: site/docs/audits/certifications/insurance (if any). - - Publish your post under the “**Node Operators > stVaults Identification**” category. - -2. **KYB(C) Verification** - - Complete KYB(C) (Know Your Business / Know Your Customer) screening via SumSub. This is required for all operators applying for any Identified category. - - 🔗 [SumSub KYB(C) Form](https://in.sumsub.com/websdk/p/uni_nqzEH2qmLTS1PowL) - - **Note:** Operators already participating in the Lido Curated Set are exempt from this SumSub step, having been onboarded and vetted through the Lido Curated Set governance process. - -3. **Node Operator Questionnaires (private)** - - You are also asked to provide technical and business detailed information. This step is required only during the initial identification process and category assignment. - - 3.1. To complete the identification process and obtain the **"Basic"** category, please fill out this form: - - 🔗 [Basic stVaults Identification form](https://tally.so/r/3xk45o). - - What information you will be asked to fill in the form: - - - Node operator details (entity, jurisdictions, contacts). - - Data for your card on the Node Operators Overview page. - - 3.2. To obtain better stETH minting terms under the **stVaults Professional Operator** category (and **stVaults Professional Trusted Operator** later on), please also fill out this form: - - 🔗 [Extended stVaults Category Application](https://tally.so/r/npjNdq). - - What information you will be asked to fill in the form: - - - **Business plan** (ETH sourcing, channels, audience, timing). - - **Infra** (clients’ set-ups, locations, server types, server providers, key generation & management, etc.). - - **Ops** (monitoring/alerting, on-call, IR runbooks, insurance, bug-bounty). - -4. **Assessment & scoring** - - You are evaluated across three main areas by the stVaults Committee: **Operational Capabilities, Decentralization & Infrastructure Distribution, and Business Case.** - -5. **Decision: Category and corresponding Tier Grid (RR & stETH minting limits)** - - The stVaults Committee assigns your **category** (Basic identified, stVaults Professional Operator), defines your **tiers grid**, and then pushes updates through **Easy Track**. The stVaults Committee publishes the reasoning behind its decision either in a post on the Lido Research Forum under the “Node Operators > stVaults Identification” category, or as a reply to the original post-request submitted by the Node Operator. - -6. **Node Operator card creation** - - The stVaults Committee creates your Node Operator card (name/logo, links, geo/jurisdiction, infra/DVT/relays, certifications/audits/insurance/bug-bounty). Your card will be displayed on the Node Operators Overview page when you have at least one stVault with at least 32 ETH of Total Value. - - _The Node Operators Overview page will follow in a later release after stVaults Mainnet._ - -7. **Communication & listing** - - Your card and tiers grid are set, and you can now continue as an Identified Node Operator. Additionally, every Identified Node Operator will have a direct communication channel with the stVaults Committee representatives in a shared Telegram group. Questions and discussions can also always be raised on the Lido Research Forum. - -### DVT Cluster identification and assessment - -Each individual Node Operator participating in the DVT Cluster must pass the identification process [as described above](#individual-node-operators-identification-and-assessment): - -1. Post an identification request on the Lido Research Forum (mandatory). -2. Complete the KYB(C) (mandatory). -3. Complete the stVaults Identification Form (mandatory). -4. Complete the extended stVaults Node Operator Category Application (required for stVaults Professional Operator category). - -After that, there are the following actions required from a representative of the DVT Cluster: - -1. **Public Request on Lido Research Forum** - - As a DVT Cluster, post your request and summary on the Lido Research Forum. - - 🔗 [Lido Research Forum](https://research.lido.fi/c/node-operators/stvaults-identification/24) - - What information to provide: - - - **Who you are**; list of Node Operators in the Cluster; your cluster name/brand. - - **Request** (become Identified DVT Cluster; any non-default requests). - - **Business case**: ETH you can acquire — scales/market size, user segments, channels, partners, timelines, fee policy. - - **DVT Technology**: Obol / SSV / or other. - - **Links**: site/docs/audits/certifications/insurance (if any). - - Publish your post under the “_Node Operators > stVaults Identification_” category. - -2. **DVT Cluster Questionnaire (private)** - - You are also asked to provide technical and business detailed information. - - 🔗 [DVT Cluster Identification form](https://tally.so/r/wAoAkW). - - What information you will be asked to fill in the form: - - - Node Operators creating the Cluster (entities, contacts). - - How you manage your keys generating process (DKG ceremony). - - Data for your card on the Node Operators Overview page. - - **Business plan** (ETH sourcing, channels, audience, timing). - -3. **Assessment & scoring** - - You are evaluated by the stVaults Committee. - -4. **Decision: Category and corresponding Tier Grid (RR & stETH minting limits)** - - In case of a positive decision, the stVaults Committee defines your **tier grid** and submits the updates through **Easy Track**. The Committee also publishes the reasoning behind its decision by replying to the original post-request submitted by the DVT Cluster representative. - -5. **Node Operator card creation** - - The stVaults Committee creates your DVT Cluster card (name/logo, links, geo/jurisdiction, etc.). Your card will be displayed on the Node Operators Overview page when you have at least one stVault with at least 32 ETH of Total Value. - - _The Node Operators Overview page will follow in a later release after stVaults Mainnet._ - -6. **Communication & listing** - - Your card and tiers grid are set, and you can now continue as an Identified DVT Cluster. Additionally, every Cluster will have a direct communication channel with the stVaults Committee representatives in a shared Telegram group. Questions and discussions can also always be raised on the Lido Research Forum. - ---- - -## **How tiers map to risk profile & business case** - -**1) Why categories exist.** - -The [Lido V3 risk assessment framework](https://research.lido.fi/t/default-risk-assessment-framework-and-fees-parameters-for-lido-v3-stvaults/10504) aims to balance growth opportunities with protection against major risks such as correlated slashing and centralization. It does this by linking qualitative signals (like operational and decentralization metrics) with quantitative ones (like stake volumes). Together, these determine how **stETH minting limits** and **Reserve Ratios** scale with each operator’s overall risk profile. Default parameters ensure protocol safety, while categories allow well-earned flexibility. - -A **Category** represents a classification of Node Operators: - -- Each Category has an associated **tier grid**, which serves as a baseline configuration for Node Operators within that Category. -- When a Node Operator is assigned to a Category based on its unique performance and characteristics, it receives tiers (with defined RRs and stETH limits) according to that Category and the Node Operator’s total stETH minting limit. - -**2) Why multiple tiers per category?** - -Each tier is designed for a distinct business case — not a linear “risk ladder.” - -- **First tiers (Tier-1..2):** **lowest RR** + **lowest stETH minting limit** → **liquidity-first** scenarios (strategy builders, looping) where liquidity matters most; stETH minting capacity **is tightly bounded**. -- **Upper tiers (Tier-3…N):** **more conservative RR** + **much higher stETH minting limit** → **volume-first** scenarios (institutions, funds, ETF/ETP) where large mints — sometimes **on demand** — matter more than high liquidity. - -**3) How RR & stETH minting limit interact.** - -In any stVault, stETH capacity depends on the Reserve Ratio and the Total Value, but is also constrained by limits: - -- stVault stETH limit (equal to Tier stETH limit by default). -- Tier stETH limit. -- Node Operator stETH limit. -- stVaults’ global stETH limit. - -![Tiers and minting parameters](/img/stvaults/tiers-and-minting-parameters.png) - -## **Governance & operational safety net.** - -In order to keep the stVaults risk framework flexible and to streamline the governance process around it, it is proposed that [the stVaults Committee](https://research.lido.fi/t/stvaults-committee-proposal/10608) will be responsible for the following actions: - -- Set the reserve ratio for specific tiers or stVaults. -- Define the default and custom tier grids for node operators. -- Set DAO fee values for specific vaults and tiers within a node operator’s grid. -- Bad debt compensation management between vaults/tiers in complex cases, like mass slashing. -- Manage Lido Core redemptions, trigger validator exits for rebalancing or redemptions, and perform other actions required in exceptional cases to keep the Lido Core protocol stable and secure, in accordance with the stVaults risk assessment framework. -- Adjusting the stVaults risk framework and the scores within the framework. - -**Easy Track** helps to speed up the process of changing parameters while securing the protocol, builders, and Node Operators from malicious actions by committee members, as these motions are vetoable by LDO token-holders. - -LDO token-holders may at any time vote to rescind or reassign these responsibilities to another group, entity, or individual, and may vote to modify, extend, or remove them entirely. - ---- - -## **References** - -- [**Default risk assessment framework and fees parameters for Lido V3 (stVaults)**](https://research.lido.fi/t/default-risk-assessment-framework-and-fees-parameters-for-lido-v3-stvaults/10504) — tiers, RR, and caps framing. -- [**stVaults Committee Proposal**](https://research.lido.fi/t/stvaults-committee-proposal/10608/6) — scope & responsibilities for non-default asks and monitoring. -- [**Lido V3 — Design & Implementation Proposal**](https://research.lido.fi/t/lido-v3-design-implementation-proposal/10665) — overall V3 context and rollout. diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/stvault-disconnect-guide.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/stvault-disconnect-guide.md deleted file mode 100644 index 54d290472..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/stvault-disconnect-guide.md +++ /dev/null @@ -1,474 +0,0 @@ ---- -sidebar_position: 6 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# 🔌 stVault Disconnect Guide - -This guide walks you through the process of disconnecting your stVault from Lido protocol. Disconnecting is a multi-step process and each step must be completed in the given order. - -## Why disconnect an stVault and what changes after - -Disconnecting an stVault is a deliberate action fully controlled by the Vault Owner. It allows the Vault Owner to remove the stVault’s connection to the Lido protocol and operate it independently. - -### Why disconnect? - -A Vault Owner may choose to disconnect for several reasons: - -- **Withdraw the connection deposit** - The 1 ETH deposit used for stVault connection can be withdrawn after disconnection. - -- **Stop using Lido protocol services** - Disconnecting disables Lido-provided accounting, liquidity by stETH, and fee mechanisms, and therefore stops Lido fee accrual. - -- **Make the stVault irrevocably independent (ossification)** - The stVault can be ossified to prevent any future upgrades or changes, effectively removing any potential influence from Lido DAO. - Disconnection does not imply ossification: ossification is an optional, separate action available after disconnection. -### What stops working after disconnection - -After disconnection, all integrations with Lido protocol components are disabled. - -**Dashboard contract is abandoned, which means:** -- Granular roles and permissions are no longer available. -- Most of the Web UI functionality becomes unavailable. -- Node Operator fee distribution stops. - -:::warning -Node Operators must independently monitor disconnection events, as validation continues after disconnection, but Node Operator fees are no longer accrued. Disconnection can be detected by monitoring the VaultDisconnectInitiated(address **indexed** vault) event emitted by the VaultHub contract on-chain. -::: - -**No connection to VaultHub:** -- All stETH-related operations are disabled: Minting, Repayment, Rebalancing. - -**No oracles reports:** -- No accounting updates are performed, including Total Value updates and any oracle-driven state changes. -- No Lido fees are charged. - -### What remains functional after disconnection - -stVault disconnection from VaultHub does not affect validators. - -The following functionality remains available **at the smart contract / CLI level:** -- Supplying ETH to the stVault. -- Predeposit Guarantee contract functionality. -- Validator operations continue unaffected: validators keep running and validation rewards continue to accrue. - -:::info -If the stVault is **not ossified**, it can be reconnected to VaultHub in the future. -::: - -## Prerequisites - -Before starting the disconnection process, make sure: - -1. **All minted stETH is repaid.** Your vault must have zero liability shares. If you have outstanding stETH minted against the vault, [repay it first](./voluntary-rebalancing-and-vault-closure.md). -2. **Your vault has a fresh oracle report.** The disconnect will revert if the report is stale. [Apply a fresh report](./applying-report-guide.md) if needed. -3. **The vault has sufficient balance to cover all unsettled fees.** Both Lido protocol fees and accrued Node Operator fees (if applicable) are settled from the vault balance during the initiation step. If the vault balance is insufficient to cover them, the transaction will revert. - -:::info -Once completed, the vault is removed from Lido protocol. However, the same vault can be reconnected later unless it has been ossified. -::: - - - - -## Step 1. Initiate voluntary disconnect - -The disconnection process starts by calling `Dashboard.voluntaryDisconnect()`. The caller must have the `VOLUNTARY_DISCONNECT_ROLE` or `DEFAULT_ADMIN_ROLE` on the Dashboard. - -This call: - -- Collects any accrued Node Operator fees and **transfers them to the Dashboard contract** as `feeLeftover`, for later recovery (see [Step 6](#step-6-recover-node-operator-fees)). -- Stops further fee accrual. -- Settles all outstanding Lido protocol fees from the vault balance to the Lido treasury. -- Marks the vault as **pending disconnection** in VaultHub. - -
- using Command-line Interface - -```bash -yarn start contracts dashboard w voluntary-disconnect -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **Dashboard** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect your wallet in the dialog window. -5. Find the `voluntaryDisconnect` method in the list and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -Once the transaction succeeds, your vault enters the **pending disconnection** state. While pending: - -- No new stETH can be minted. -- No ETH can be withdrawn through VaultHub. -- The vault awaits the next oracle report to finalize the disconnection. - -## Step 2. Apply the next oracle report - -Wait for the next oracle report, then apply the report data to your vault via `LazyOracle.updateVaultData()`. This is the step that **finalizes** the disconnection. - -:::info -Normally the oracle report occurs daily shortly after 12 PM UTC. -::: - -When the oracle report is applied and the report timestamp is after your disconnect initiation: - -- If there are no slashing obligations and no remaining liability shares, the disconnect **completes successfully**. VaultHub transfers ownership of the StakingVault to the Dashboard and removes all vault records. -- If slashing was reported or liabilities remain, the disconnect is **aborted** and the vault returns to connected state. - -This is a **permissionless operation** — anyone can apply the report. - -
- using Command-line Interface - -```bash -yarn start report w submit -v -``` - -The CLI automatically fetches the latest report CID, retrieves the Merkle tree from IPFS, generates the proof, and submits the transaction. - -
-
- using Etherscan UI - -1. Query the **LazyOracle** contract's `latestReportData()` method to get the current `reportCid`. -2. Fetch the Merkle tree JSON from IPFS using the CID: `https://ipfs.io/ipfs/` -3. Locate your vault's entry in the tree and extract the data fields and proof. -4. Open **Etherscan** and navigate to the **LazyOracle** contract by its address (available in the stVaults contract addresses list, see [Basic stVault with optional liquidity: Environments](../building-guides/basic-stvault#environments)). -5. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -6. Open the **Contract** tab → **Write as Proxy**. -7. Click **Connect to Web3** and connect your wallet in the dialog window. -8. Find the `updateVaultData` method in the list, fill out the fields with the data from IPFS, and click **Write**. -9. Sign the transaction in your wallet. -10. Click **View your transaction** and wait for it to be executed. - -
- -:::info -You can verify the disconnection completed by calling `VaultHub.isVaultConnected(vaultAddress)` or checking for the `VaultDisconnectCompleted` event in the transaction logs. If the disconnect was aborted due to slashing or liabilities, a `VaultDisconnectAborted` event will appear instead, and you will need to resolve the issue before trying again. -::: - -For more about applying report, read [Applying Oracle Reports](./applying-report-guide.md). - -## Step 3. Abandon Dashboard and transfer ownership - -After disconnection completes, the Dashboard holds pending ownership of the StakingVault. Since the Dashboard is tightly coupled to VaultHub, you need to transfer ownership away from it to your account. - -Call `Dashboard.abandonDashboard(newOwner)`. This: - -- Accepts the pending ownership on behalf of the Dashboard. -- Initiates an ownership transfer to the specified `newOwner` address. - -The caller must have `DEFAULT_ADMIN_ROLE` on the Dashboard. The `newOwner` can be any account including the current vault owner (`DEFAULT_ADMIN_ROLE`) **except** the Dashboard itself. - -
- using Command-line Interface - -```bash -yarn start contracts dashboard w abandon-dashboard -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **Dashboard** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect your wallet in the dialog window. -5. Find the `abandonDashboard` method in the list, enter the new owner address, and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -## Step 4. Accept ownership - -The StakingVault uses a two-step ownership transfer. After the Dashboard initiates the transfer in the previous step, you must accept it from the `newOwner` address. - -Call `StakingVault.acceptOwnership()` from the address specified as `newOwner` in the previous step. - -
- using Command-line Interface - -```bash -yarn start contracts vault w accept-ownership -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **StakingVault** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet for the `newOwner` address. -5. Find the `acceptOwnership` method and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -After this step, you are the full owner of the StakingVault with no dependency on VaultHub or the Dashboard. - -## Step 5. Withdraw ETH - -When your vault was connected to VaultHub, 1 ETH was locked as a connection deposit (minimal reserve). Now that the vault is fully disconnected, you can withdraw this deposit along with any other remaining balance. - -Call `StakingVault.withdraw(recipient, amount)` from the owner address. - -
- using Command-line Interface - -```bash -yarn start contracts vault w withdraw -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **StakingVault** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet for the `newOwner` address. -5. Find the `withdraw` method in the list and fill out the fields: - - `_recipient`: the address to receive the ETH. - - `_ether`: the amount in wei (e.g., `1000000000000000000` for 1 ETH). -6. Click **Write** and sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -## Step 6. Recover Node Operator fees - -During Step 1, accrued Node Operator fees were withdrawn from the vault and stored on the Dashboard contract as `feeLeftover` rather than sent directly to the `feeRecipient`. This is intentional: if the `feeRecipient` were a contract that rejects ETH transfers, sending fees directly would revert and block the disconnect. - -To send the stored fees to the configured `feeRecipient`, call `Dashboard.recoverFeeLeftover()`. This is a **permissionless operation**, anyone can call it, and the fees will be sent to the `feeRecipient` address configured on the Dashboard. - -
- using Command-line Interface - -```bash -yarn start contracts dashboard w recover-fee-leftover -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **Dashboard** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect your wallet in the dialog window. -5. Find the `recoverFeeLeftover` method in the list and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -
- - -## Step 1. Initiate voluntary disconnect - -Call `VaultHub.voluntaryDisconnect(vaultAddress)` directly. The caller must be the vault's owner as recorded in VaultHub (`connection.owner`). - -This call: - -- Settles all outstanding Lido protocol fees from the vault balance to the Lido treasury. -- Marks the vault as **pending disconnection** in VaultHub. - -
- using Command-line Interface - -```bash -yarn start contracts hub w v-owner-disconnect -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **VaultHub** contract by its address (available in the stVaults contract addresses list, see [Basic stVault with optional liquidity: Environments](../building-guides/basic-stvault#environments)). -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet for the `connection.owner` address. -5. Find the `voluntaryDisconnect` method in the list, enter your vault address, and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -Once the transaction succeeds, your vault enters the **pending disconnection** state. While pending: - -- No new stETH can be minted. -- No ETH can be withdrawn through VaultHub. -- The vault awaits the next oracle report to finalize the disconnection. - -## Step 2. Apply the next oracle report - -Wait for the next oracle report, then apply the report data to your vault via `LazyOracle.updateVaultData()`. This is the step that **finalizes** the disconnection. - -:::info -Normally the oracle report occurs daily shortly after 12 PM UTC. -::: - -When the oracle report is applied and the report timestamp is after your disconnect initiation: - -- If there are no slashing obligations and no remaining liability shares, the disconnect **completes successfully**. VaultHub transfers ownership of the StakingVault to `connection.owner` and removes all vault records. -- If slashing was reported or liabilities remain, the disconnect is **aborted** and the vault returns to connected state. - -This is a **permissionless operation** — anyone can apply the report. - -
- using Command-line Interface - -```bash -yarn start report w submit -v -``` - -The CLI automatically fetches the latest report CID, retrieves the Merkle tree from IPFS, generates the proof, and submits the transaction. - -
-
- using Etherscan UI - -1. Query the **LazyOracle** contract's `latestReportData()` method to get the current `reportCid`. -2. Fetch the Merkle tree JSON from IPFS using the CID: `https://ipfs.io/ipfs/` -3. Locate your vault's entry in the tree and extract the data fields and proof. -4. Open **Etherscan** and navigate to the **LazyOracle** contract by its address (available in the stVaults contract addresses list, see [Basic stVault with optional liquidity: Environments](../building-guides/basic-stvault#environments)). -5. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -6. Open the **Contract** tab → **Write as Proxy**. -7. Click **Connect to Web3** and connect your wallet in the dialog window. -8. Find the `updateVaultData` method in the list, fill out the fields with the data from IPFS, and click **Write**. -9. Sign the transaction in your wallet. -10. Click **View your transaction** and wait for it to be executed. - -
- -:::info -You can verify the disconnection completed by calling `VaultHub.isVaultConnected(vaultAddress)` or checking for the `VaultDisconnectCompleted` event in the transaction logs. If the disconnect was aborted due to slashing or liabilities, a `VaultDisconnectAborted` event will appear instead, and you will need to resolve the issue before trying again. -::: - -For more about applying report, read [Applying Oracle Reports](./applying-report-guide.md). - -## Step 3. Accept ownership - -The StakingVault uses a two-step ownership transfer. After the disconnect completes, VaultHub transfers pending ownership to `connection.owner`. You must accept it from that address. - -Call `StakingVault.acceptOwnership()` from the `connection.owner` address. - -
- using Command-line Interface - -```bash -yarn start contracts vault w accept-ownership -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **StakingVault** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet for the `connection.owner` address. -5. Find the `acceptOwnership` method and click **Write**. -6. Sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -After this step, you are the full owner of the StakingVault with no dependency on VaultHub. - -## Step 4. Withdraw ETH - -When your vault was connected to VaultHub, 1 ETH was locked as a connection deposit (minimal reserve). Now that the vault is fully disconnected, you can withdraw this deposit along with any other remaining balance. - -Call `StakingVault.withdraw(recipient, amount)` from the owner address. - -
- using Command-line Interface - -```bash -yarn start contracts vault w withdraw -``` - -
-
- using Etherscan UI - -1. Open **Etherscan** and navigate to the **StakingVault** contract by its address. -2. Since this contract is a proxy, complete the verification steps once (if not done before): - - Go to **Contract → Code**. - - Click **More options**. - - Select **Is this a proxy?**. - - Click **Verify** in the dialog. - - Return to the contract details page. -3. Open the **Contract** tab → **Write as Proxy**. -4. Click **Connect to Web3** and connect the wallet for the owner address. -5. Find the `withdraw` method in the list and fill out the fields: - - `_recipient`: the address to receive the ETH. - - `_ether`: the amount in wei (e.g., `1000000000000000000` for 1 ETH). -6. Click **Write** and sign the transaction in your wallet. -7. Click **View your transaction** and wait for it to be executed. - -
- -
-
diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/stvaults-economy-examples.mdx b/run-on-lido/stvaults-legacy/operational-and-management-guides/stvaults-economy-examples.mdx deleted file mode 100644 index 65c83d297..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/stvaults-economy-examples.mdx +++ /dev/null @@ -1,326 +0,0 @@ ---- -sidebar_position: 4 ---- - -# 🧮 stVaults Economy Examples - -Here you’ll find three typical economic examples of products built on top of stVaults. -These simplified models are designed to clearly highlight the key metrics and factors that influence the overall economics of each product. - -
- - ## 1. stVaults-based DeFi Product - - - - As an example, we consider a personalized staking setup with a single Node Operator, full utilization of available - stETH Minting Capacity, and subsequent use of stETH in DeFi to add an additional layer of rewards. - - ### Annualized Economics Breakdown - -

Staking Rewards

- -
- Gross Staking Rewards - - 3.2 ETH -
- - Validators generate staking rewards on top of the 100 ETH deposited to the Beacon Chain. - e.g., 3.2% Staking APR. - -
- Node Operator Fee - - - 0.096 ETH -
- - Set per stVault through consensus between the Vault Owner and the Node Operator. - e.g., 3% out of Gross Staking Rewards earned. - -
- Lido Fee - - - 0.1728 ETH -
- - In this example, the annual Lido Fee approximately equals to 6% of the Lido Core Gross APR and can be calculated by - the equation: - Lido Fee = 6% * 3.2% Lido Core Gross APR * 90 stETH = 0.1728 ETH; - e.g., Lido Core Gross APR ~ 3.2%. - -

stETH Liability - Growth

- -
- Minted stETH Rebase - - 2.592 stETH -
- - The stVault’s liquidity is provided in stETH, a rebasing token — its balance updates daily to reflect accrued staking - rewards. - To ensure the Vault Owner’s repayment amount is always accurately represented, the minted stETH liability adjusts daily in - line with stETH’s rebasing mechanics. - This is primarily a technical adjustment, as the liability increase is offset by the rewards the Vault Owner earns as a - holder of stETH. - e.g., stETH APR ~ 2.88%. - -

stVault Bottom - Line

- - A positive stVault Efficiency indicates that the Node Operator’s performance is sufficient to cover the growth of the - stETH Liability. - -
- stVault Bottom Line - - + 0.3392 ETH -
- -
- stVault Efficiency - - 0.3392% -
- - - ### stETH Usage Outside the stVault - - The Vault Owner generates primary profit by using minted stETH in DeFi protocols: - - **+ 0.3392%** — stVault Efficiency upside - - **+ 2.592%** — minted stETH APR (normalized to stVault Total Value 100 ETH) - - **+ 2.53%** — additional APR from DeFi strategy (normalized to stVault Total Value 100 ETH) - -
- Total APR - - 5.4612% -
- -
- --- - - - ## 2. Institutional Staking - - - - As an example, consider a digital neobank that requires liquid staking through a personalized setup with a single Node - Operator, full utilization of the available stETH minting capacity, - and storage of the minted stETH in a licensed custody solution. - - ### Annualized Economics Breakdown - -

Staking Rewards

- -
- Gross Staking Rewards - - 3.2 ETH -
- - Validators generate staking rewards on top of the 100 ETH deposited to the Beacon Chain. - e.g., 3.2% Staking APR. - -
- Node Operator Fee - - - 0.096 ETH -
- Set per stVault through consensus between the Vault Owner and the Node Operator. - e.g., 3% out of Gross Staking Rewards earned. - -
- Lido Fee - - - 0.1728 ETH -
- In this example, the annual Lido Fee approximately equals 6% of the Lido Core Gross APR and can be calculated by - the equation: - Lido Fee = 6% * 3.2% Lido Core Gross APR * 90 stETH = 0.1728 ETH; - e.g., Lido Core Gross APR ~ 3.2%. - -

stETH Liability - Growth

- -
- Minted stETH Rebase - - 2.592 stETH -
- The stVault’s liquidity is provided in stETH, a rebasing token — its balance updates daily to reflect accrued staking - rewards. - To ensure the Vault Owner’s repayment amount is always accurately represented, the minted stETH liability adjusts daily in - line with stETH’s rebasing mechanics. - This is primarily a technical adjustment, as the liability increase is offset by the rewards the Vault Owner earns as a - holder of stETH. - e.g., stETH APR ~ 2.88%. - -

stVault Bottom - Line

-
- stVault Bottom Line - - + 0.3392 ETH -
-
- stVault Efficiency - - 0.3392% -
- A positive stVault Efficiency indicates that the Node Operator’s performance is sufficient to cover the growth of the - stETH Liability. - - - ### stETH Usage Outside the stVault - - The Vault Owner generates primary profit via higher validation performance than Lido Core APR plus rewards received as - a stETH holder. - - **+ 0.3392%** — stVault Efficiency upside - - **+ 2.592%** — minted stETH APR (normalized to stVault Total Value 100 ETH) - -
- Total APR - - 2.9312% -
- -
- --- - - ## 3. Leveraged Staking - - - - As an example, we consider a personalized staking setup involving a single Node Operator, - full utilization of the available stETH minting capacity, and recursive leverage through external lending markets. - -

In our example

- -
- Leverage multiplier: - - ~9×; -
-
- tVault — Total Value: - - 894.85 ETH; -
-
- stVault — Total stETH Minting Capacity: - - 850.11 stETH; -
-
- stVault — stETH Liability: - - 850.11 stETH; -
-
- Lending Market — stETH Used as Collateral: - - 850.11 stETH; -
-
- Lending Market — ETH Borrowed: - - 794.85 ETH; -
-
- Vault Owner's Principal ETH: - - only the initial 100 ETH. -
- - - ### Annualized Economics Breakdown - -

Staking Rewards

- -
- Gross Staking Rewards - - 30.4251 ETH -
- - Validators generate staking rewards on top of the 100 ETH deposited to the Beacon Chain. - e.g., 3.4% Staking APR. - -
- Node Operator Fee - - - 1.217 ETH -
- Set per stVault through consensus between the Vault Owner and the Node Operator. - e.g., 4% out of Gross Staking Rewards earned. - -
- Lido Fee - - - 1.6322 ETH -
- In this example, the annual Lido Fee approximately equals 6% of the Lido Core Gross APR and can be calculated by - the equation: - Lido Fee = 6% * 3.2% Lido Core Gross APR * 850.11 stETH = 1.6322 ETH; - e.g., Lido Core Gross APR ~ 3.2%. - -

stETH Liability - Growth

- -
- Minted stETH Rebase - - 24.4832 stETH -
- The stVault’s liquidity is provided in stETH, a rebasing token — its balance updates daily to reflect accrued staking - rewards. - To ensure the Vault Owner’s repayment amount is always accurately represented, the minted stETH liability adjusts daily in - line with stETH’s rebasing mechanics. - This is primarily a technical adjustment, as the liability increase is offset by the rewards the Vault Owner earns as a - holder of stETH. - e.g., stETH APR ~ 2.88%. - -

stVault Bottom - Line

-
- stVault Bottom Line - - + 3.0926 ETH -
-
- stVault Efficiency - - 3.0926% -
- A positive stVault Efficiency indicates that the Node Operator’s performance is sufficient to cover the growth of the - stETH Liability. - - - ### stETH Usage Outside the stVault - - The Vault Owner used the minted stETH to loop through a lending market in order to amplify staking rewards. - Additional income and expenses from the lending market: - - **+ 24.4832 stETH** — rebase rewards from stETH used as collateral on the lending market - - **+ 2.5503 stETH** — supply-side rewards from the lending market - - **- 21.1431 ETH** — interest paid on borrowed ETH - -
- Total rewards - - 8.983 ETH -
-
- Total APR - - 8.983% -
- - Total APR is normalized to the Vault Owner’s initial 100 ETH. - - (!) Note: All lending market parameters are illustrative. Actual values depend on the specific product and prevailing - market conditions. (!) - -
- diff --git a/run-on-lido/stvaults-legacy/operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md b/run-on-lido/stvaults-legacy/operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md deleted file mode 100644 index 6e38053aa..000000000 --- a/run-on-lido/stvaults-legacy/operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -sidebar_position: 4 ---- - -# 🔄 Volunteering Rebalancing and Vault Closure - -## TLDR - -- **To close a stVault and withdraw all ETH**, you must first eliminate the stETH Liability entirely. -- **Option 1:** Acquire stETH externally and repay it to the stVault to reduce the liability. -- **Option 2:** Use voluntary rebalancing to transfer ETH from the stVault to Lido Core, writing off debt at a 1:1 ratio. -- Once the liability is cleared, the remaining ETH becomes fully withdrawable. - ---- - -## 📚 Definitions - -- **Voluntary Rebalancing** — a Vault Owner-initiated action that transfers ETH from the stVault to Lido Core, writing off the equivalent stETH liability at a 1:1 ratio. -- **Reserve Ratio (RR)** — defines the amount of ETH that will be reserved as part of the collateral when the Vault Owner mints stETH in the stVault. stETH isn’t minted for this amount. -- **stETH Liability** — the amount of stETH that the Vault Owner minted in the stVault, backed by the ETH collateral. Increases daily due to the stETH rebase. -- **Total Value** — the total amount of ETH, consisting of ETH staked on validators plus ETH held in the stVault Balance. Rewards accrue to both and increase Total Value. -- **stVault Balance** — the portion of ETH held directly in the StakingVault contract, not staked on validators. Only stVault Balance ETH can be used for rebalancing or withdrawal. -- **Validator Balance** — the portion of ETH staked on validators. To make this ETH available for rebalancing, you must first request validator exits and wait for the exit to complete. - ---- - -## 🔍 Why you need to repay stETH Liability to close an stVault - -When you mint stETH against your stVault, you create a **debt obligation** — the stETH Liability. The stVault’s ETH serves as collateral backing that liability. - -You cannot simply withdraw all ETH while stETH Liability remains outstanding. To close the stVault and unlock your ETH, you must first eliminate the liability entirely. - -There are two ways to do this: - -1. **Repay stETH** — acquire stETH externally and repay it back to the stVault to reduce the liability directly. -2. **Voluntary rebalancing** — transfer ETH from the stVault Balance to Lido Core, which writes off the equivalent stETH Liability at a 1:1 ratio. - -Once the liability reaches zero, and it's confirmed by a fresh Oracle report, the remaining ETH in the stVault is unlocked to withdraw. - ---- - -## 📝 Option 1 — repay stETH - -The standard way to reduce stETH Liability is to acquire stETH and repay it back to the stVault. - -### How it works - -1. Acquire stETH equal to your stETH Liability (e.g., buy on a DEX, swap ETH → stETH, or use stETH you already hold). -2. Repay the stETH back to the stVault. Each stETH repay reduces the stETH Liability by the same amount. -3. Once the full liability is repaid, the stVault’s ETH is fully withdrawable. - -### Calculation - -`stETH to Repay = stETH Liability` - -For example, an stVault with 1000 ETH Total Value and 400 stETH minted: acquire and repay **400 stETH**. - -After repaying, the stVault has 1,000 ETH with zero liability — all of it is withdrawable (once validators are exited and ETH is back in stVault balance, and a fresh Oracle report is applied to the stVault). - ---- - -## 📝 Option 2 — Voluntary rebalancing - -If you do not have or do not wish to acquire stETH externally, you can use voluntary rebalancing to repay the liability using the stVault’s own ETH. - -### How it works - -1. Transfer ETH from the stVault balance to Lido Core. -2. Lido Core writes off the equivalent stETH debt at a 1:1 ratio. -3. The stVault’s stETH Liability decreases by the amount of ETH transferred. - -### Trade-offs compared to repaying stETH - -- **Cons:** Reduces the stVault’s Total Value. To repay 400 stETH, you spend 400 ETH from the stVault — leaving you with less ETH to withdraw at the end. -- **Cons:** Requires sufficient stVault balance (not validator balance), so you may need to exit validators before rebalancing. -- **Pros:** No need to acquire stETH externally or interact with DEXes. - -### How to calculate the ETH needed - -To **fully close the stVault**, you are repaying the entire stETH debt. Since voluntary rebalancing writes off stETH at a 1:1 ratio for each ETH transferred, the total ETH required equals the full stETH Liability (**full rebalancing**): - -`ETH for full repayment = stETH Liability` - ---- - -## 🔍 Example: closing an stVault with 1,000 ETH and 400 stETH minted - -### Initial stVault state - -| Metric | Value | -| --- | --- | -| Total Value | 1,000 ETH | -| — Validator Balance | 960 ETH (30 validators × 32 ETH) | -| — stVault Balance | 40 ETH | -| Reserve Ratio (RR) | 5% | -| stETH Liability (minted stETH) | 400 stETH | - -### Path A — Repay stETH - -1. Acquire 400 stETH externally. -2. Repay 400 stETH against the stVault. stETH Liability drops to **0**. -3. Exit all 30 validators. Wait for ETH to be swept back to the stVault balance. -4. Withdraw all 1,000 ETH. - -| Metric | Before | After repay | After withdrawal | -| --- | --- | --- | --- | -| Total Value | 1,000 ETH | 1,000 ETH | 0 ETH | -| stETH Liability | 400 stETH | 0 stETH | 0 stETH | -| ETH withdrawn | — | — | 1,000 ETH | - -**Result:** You recover all 1,000 ETH from the stVault (minus any unsettled fees). The 400 stETH used to repay was acquired externally. - -### Path B — Voluntary rebalancing - -Voluntary rebalancing can only use ETH from the **stVault Balance** (40 ETH here), not from validators directly. Since the full repayment requires 400 ETH, you must exit validators first to move enough ETH into the stVault Balance. - -**Step 1 — Exit validators to free up ETH** - -You need 400 ETH available in the stVault Balance to fully repay the stETH Liability. Currently, only 40 ETH is available — the remaining 960 ETH is locked on validators. - -Request exits for enough validators to cover the shortfall: - -`ETH shortfall = stETH Liability − stVault Balance = 400 − 40 = 360 ETH` - -At 32 ETH per validator, you need to exit at least **12 validators** (12 × 32 = 384 ETH) to cover the 360 ETH shortfall. - -After the exits complete and ETH is swept back to the stVault: - -| Metric | Value | -| --- | --- | -| Total Value | 1,000 ETH | -| — Validator Balance | 576 ETH (18 validators × 32 ETH) | -| — stVault Balance | 424 ETH | - -The stVault Balance now has enough ETH to cover the full 400 ETH rebalance. - -**Step 2 — Calculate the ETH for full rebalancing** - -To eliminate all stETH Liability, you must rebalance the full 400 ETH: - -`ETH for full repayment = stETH Liability = 400 ETH` - -**Step 3 — Execute voluntary rebalancing** - -Initiate a voluntary rebalance of **400 ETH**: - -1. The stVault transfers 400 ETH to Lido Core. -2. Lido Core writes off 400 stETH debt at a 1:1 ratio. -3. The stVault’s stETH Liability drops from 400 stETH to **0 stETH**. - -**Post-rebalancing stVault state** - -| Metric | Before | After | -| --- | --- | --- | -| Total Value | 1,000 ETH | 600 ETH | -| — Validator Balance | 576 ETH | 576 ETH | -| — stVault Balance | 424 ETH | 24 ETH | -| stETH Liability | 400 stETH | 0 stETH | - -**Step 4 — Withdraw remaining ETH** - -With stETH Liability at zero, the remaining **600 ETH** is fully withdrawable. No collateral is locked, and no reserve requirements apply. - -Of this 600 ETH, 24 ETH is already in the stVault Balance and can be withdrawn immediately. The remaining 576 ETH is still on validators — exit the remaining 18 validators and withdraw once the ETH is swept back to the stVault. - -**Result:** You recover 600 ETH from the stVault. The other 400 ETH was spent on rebalancing. - -Keep in mind that **unsettled fees** may reduce the actual withdrawable amount. Fees accrue daily and are deducted from the stVault’s Total Value. Ensure all fees are settled before calculating the final withdrawal amount. - ---- - -## ❗️Important considerations - -### stETH Liability grows over time - -stETH Liability increases daily due to the stETH rebase. If you calculated 400 stETH today, the actual liability at the time of execution may be slightly higher. Always use the **current** stETH Liability value when executing the repay or rebalance. - -### stVault balance vs. staked ETH - -Voluntary rebalancing and withdrawals can only use the stVault's **available balance** (unstaked ETH). If the stVault’s ETH is primarily staked on validators, you must first exit enough validators and wait for the ETH to become available in the stVault Balance. - -### Partial closure - -If you do not have enough stETH or liquid ETH to repay the full liability at once, you can repay in stages — using multiple repays, multiple voluntary rebalances, or a combination of both. Each action reduces the stETH Liability. - -### Fees - -Unsettled fees reduce the effective Total Value. Factor in accrued fees when planning the closure to avoid a shortfall. \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/qualified-custodians/cactus.md b/run-on-lido/stvaults-legacy/qualified-custodians/cactus.md deleted file mode 100644 index 27c92c912..000000000 --- a/run-on-lido/stvaults-legacy/qualified-custodians/cactus.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 🔐 Cactus Custody -## stVaults user flow for Cactus Custody customers - -This guide explains how Cactus Custody clients can connect to the stVaults Web UI and interact with stVaults smart contracts using Cactus Link. - -Cactus Link is a browser extension that works like one of the popular hot wallets. - -## Connecting Cactus Link to the stVaults Web UI -### 1. In your browser: -Ensure that the [Cactus Link](https://chromewebstore.google.com/detail/cactus-link/chiilpgkfmcopocdffapngjcbggdehmj) browser extension is installed in [Chrome](https://www.google.com/chrome). Please confirm with your Administrator that the required permissions have been configured to connect your DeFi account to Cactus Link. For more details, refer to the [Cactus Link guide](https://manual.mycactus.com/defi/cactus-link). - -#### 1.1. Open browser extension UI: -Cactus Link UI: Locked screen -Cactus Link UI: Main screen - -#### 1.2. Select network and address to connect: -Cactus Link UI: Main screen -Cactus Link UI: Selecting the network -Cactus Link UI: Selecting the wallet - -### 2. In the stVaults Web UI: -#### 2.1 Open stVaults Web UI and click "Connect wallet" -- Mainnet: https://stvaults.lido.fi/ -- Hoodi testnet: https://stvaults-hoodi.testnet.fi/ - -stVaults Web UI - -#### 2.2. Click "Browser" button in the dialog window. -stVaults Web UI: Connect wallet - -#### 2.3. Connection established. -Your Cactus Link wallet address will now appear as connected, and you can create and manage stVaults. -stVaults Web UI: Connection established - -## Whitelisting smart contract addresses -To use the stVaults infrastructure, the stVaults smart contracts must be whitelisted for interaction. Please ask your administrator to add the required stVaults contract addresses to the whitelist. - -You can find the addresses required for whitelisting in the [Custodians overview list](./index.md#whitelisting-smart-contract-addresses). - -## Useful guides -- [Create a Basic stVault with optional liquidity](../building-guides/basic-stvault.md) -- [Health Monitoring Guide](../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../operational-and-management-guides/health-emergency-guide.md) -- [Voluntary Rebalancing and Vault Closure](../operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md) \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/qualified-custodians/copper.md b/run-on-lido/stvaults-legacy/qualified-custodians/copper.md deleted file mode 100644 index 6303e1caa..000000000 --- a/run-on-lido/stvaults-legacy/qualified-custodians/copper.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -sidebar_position: 2 ---- - -# 🔐 Copper -## stVaults user flow for Copper customers - -This guide explains how Copper clients can connect to the stVaults Web UI and interact with stVaults smart contracts using CopperConnect. - -CopperConnect is a browser extension that works like one of the popular hot wallets. - -## Connecting CopperConnect to the stVaults Web UI -### 1. In your browser: -Make sure that you've installed and configured the CopperConnect browser extension. - -#### 1.1. Open browser extension UI: -CopperConnect UI: Login -CopperConnect UI: Main screen - -#### 1.2. Select Organization and Account to connect: -CopperConnect UI: Organization -CopperConnect UI: Account - -### 2. In the stVaults Web UI: -#### 2.1 Open stVaults Web UI and click "Connect wallet" -- Mainnet: https://stvaults.lido.fi/ -- Hoodi testnet: https://stvaults-hoodi.testnet.fi/ - -stVaults Web UI - -#### 2.2. Click "Browser" button in the dialog window. -stVaults Web UI: Connect wallet - -#### 2.3. Connection established. -Your CopperConnect wallet address will now appear as connected, and you can create and manage stVaults. -stVaults Web UI: Connection established - -## Whitelisting smart contract addresses -To use the stVaults infrastructure, the stVaults smart contracts must be whitelisted for interaction. Please ask your administrator to add the required stVaults contract addresses to the whitelist. - -You can find the addresses required for whitelisting in the [Custodians overview list](./index.md#whitelisting-smart-contract-addresses). - -## Useful guides -- [Create a Basic stVault with optional liquidity](../building-guides/basic-stvault.md) -- [Health Monitoring Guide](../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../operational-and-management-guides/health-emergency-guide.md) -- [Voluntary Rebalancing and Vault Closure](../operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md) \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/qualified-custodians/fireblocks.md b/run-on-lido/stvaults-legacy/qualified-custodians/fireblocks.md deleted file mode 100644 index e934273bf..000000000 --- a/run-on-lido/stvaults-legacy/qualified-custodians/fireblocks.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 🔐 Fireblocks -## stVaults user flow for Fireblocks customers - -This guide explains how Fireblocks clients can connect to the stVaults Web UI and interact with stVaults smart contracts using institutional approval workflows. - -## Connecting Fireblocks to the stVaults Web UI -### 1. In the stVaults Web UI: -#### 1.1 Open stVaults Web UI and click "Connect wallet" -- Mainnet: https://stvaults.lido.fi/ -- Hoodi testnet: https://stvaults-hoodi.testnet.fi/ - -stVaults Web UI - -#### 1.2. Click "WalletConnect" button in the dialog window. -stVaults Web UI: Connect wallet - -#### 1.3. You will see a QR code. -stVaults Web UI: Connect wallet: QR Code - -### 2. In Fireblocks app on your phone: -#### 2.1. Navigate to the Web3 Wallet section, tap the “Scan” icon, and scan the QR code. -#### Choose a User to connect. -Fireblocks UI: Choose a User to connect -
- -#### 2.2. Choose an account to connect. -Fireblocks UI: Choose an account to connect -
- -#### 2.3. Configure preferences and tap "Connect". -Fireblocks UI: Configure preferences and proceed -
- -#### 2.4. Connection established. -Fireblocks UI: Connection established - -### 3. In the stVaults Web UI: -Your Fireblocks wallet address will now appear as connected, and you can create and manage stVaults. - stVaults Web UI: Fireblocks wallet is connected - -## Whitelisting smart contract addresses -To use the stVaults infrastructure, the stVaults smart contracts must be whitelisted for interaction. Please ask your administrator to add the required stVaults contract addresses to the whitelist. - -You can find the addresses required for whitelisting in the [Custodians overview list](./index.md#whitelisting-smart-contract-addresses). - -## Useful guides -- [Create a Basic stVault with optional liquidity](../building-guides/basic-stvault.md) -- [Health Monitoring Guide](../operational-and-management-guides/health-monitoring-guide.md) -- [Health Emergency Guide](../operational-and-management-guides/health-emergency-guide.md) -- [Voluntary Rebalancing and Vault Closure](../operational-and-management-guides/voluntary-rebalancing-and-vault-closure.md) \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/qualified-custodians/index.md b/run-on-lido/stvaults-legacy/qualified-custodians/index.md deleted file mode 100644 index a2bd1996d..000000000 --- a/run-on-lido/stvaults-legacy/qualified-custodians/index.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -sidebar_position: 5 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# 🏛️ Qualified Custodians Supporting stVaults - -This page outlines which **Qualified Custodians** support interaction with **stVaults**, and how institutional stakers can access stVaults depending on their custody setup. - -This resource is useful for: - -- **Node Operators** offering stVaults to institutional clients -- **Institutional clients** evaluating custody options - ---- - -## **stVaults Technical Requirements** - -To interact with stVaults, a custodian must support: - -- Ethereum mainnet custody -- Arbitrary smart contract interactions -- ERC-20 token custody -- stETH and/or wstETH Ethereum tokens integrated - -To interact with the [native stVaults Web UI](https://stvaults.lido.fi/), the custodian must support DeFi connectivity, such as WalletConnect or an equivalent dApp connection method. - ---- - -## **Custodian Compatibility Matrix** - -:::info -Support may vary by jurisdiction, entity, and onboarding scope. Clients should confirm details directly with their custodian. -::: - -| Custodian | stETH Support | wstETH Support | stVaults Web UI integration | Official website | -| --- | --- | --- | --- | --- | -| [Fireblocks](./fireblocks.md) | ✅ | ✅ | WalletConnect | https://www.fireblocks.com/ | -| [Copper](./copper.md) | ✅ | ✅ | CopperConnect Browser Extension | https://copper.co/ | -| [Cactus Custody](./cactus.md) | ✅ | ✅ | Cactus Link | https://www.mycactus.com/ | -| BitGo | ✅ | ✅ | WalletConnect | https://www.bitgo.com/ | -| Anchorage | | ✅ | WalletConnect | https://www.anchorage.com/ | -| Komainu | ✅ | ✅ | WalletConnect | https://komainu.com/ | -| Hex Trust | ✅ | ✅ | WalletConnect | https://www.hextrust.com/ | - ---- - -## Whitelisting smart contract addresses -To use the stVaults infrastructure, the relevant stVaults smart contracts must be whitelisted for interaction. Please ask your administrator or custodian support team to add the required stVaults contract addresses to the whitelist. - -Some addresses must be whitelisted before creating your first vault, while vault-specific addresses can only be added after a vault has been created. We recommend whitelisting the core stVaults infrastructure addresses upfront, and adding individual vault contract addresses as new stVaults are deployed. - -### stVaults infrastructure addresses to be whitelisted - - -| Smart Contract | Address | Description | -| -------- | -------- | -------- | -| `VaultFactory` | [`0x02Ca7772FF14a9F6c1a08aF385aA96bb1b34175A`](https://etherscan.io/address/0x02Ca7772FF14a9F6c1a08aF385aA96bb1b34175A) | Factory for deploying `StakingVault` + `Dashboard` pairs using a beacon proxy. [Learn more](/contracts/staking-vault-factory/) | -| `VaultHub` | [`0x1d201BE093d847f6446530Efb0E8Fb426d176709`](https://etherscan.io/address/0x1d201BE093d847f6446530Efb0E8Fb426d176709) | Central registry and lifecycle manager for StakingVaults connected to the Lido protocol. Handles vault connection, minting/burning stETH against vault collateral, rebalancing, fee settlement, and bad debt management. [Learn more](/contracts/vault-hub/) | -| `PredepositGuarantee` | [`0xF4bF42c6D6A0E38825785048124DBAD6c9eaaac3`](https://etherscan.io/address/0xF4bF42c6D6A0E38825785048124DBAD6c9eaaac3) | PredepositGuarantee (PDG) mitigates deposit frontrunning by requiring a node operator guarantee and validator withdrawal credentials proofs (EIP-4788) before activating staged deposits. [Learn more](/contracts/predeposit-guarantee/)| -| `LazyOracle` | [`0x5DB427080200c235F2Ae8Cd17A7be87921f7AD6c`](https://etherscan.io/address/0x5DB427080200c235F2Ae8Cd17A7be87921f7AD6c) | Oracle adapter for stVaults. Stores per-vault reports, applies sanity checks, and forwards vault updates to VaultHub. [Learn more](/contracts/lazy-oracle/) | -| `OperatorGrid` | [`0xC69685E89Cefc327b43B7234AC646451B27c544d`](https://etherscan.io/address/0xC69685E89Cefc327b43B7234AC646451B27c544d) | Registry for node operators, groups, and tier parameters that define share limits, reserve ratios, and fee schedules for stVaults. [Learn more](/contracts/operator-grid/) | - - -| Smart Contract | Address | Description | -| -------- | -------- | -------- | -| `VaultFactory` | [`0x7Ba269a03eeD86f2f54CB04CA3b4b7626636Df4E`](https://hoodi.etherscan.io/address/0x7Ba269a03eeD86f2f54CB04CA3b4b7626636Df4E) | Factory for deploying `StakingVault` + `Dashboard` pairs using a beacon proxy. [Learn more](/contracts/staking-vault-factory/) | -| `VaultHub` | [`0x4C9fFC325392090F789255b9948Ab1659b797964`](https://hoodi.etherscan.io/address/0x4C9fFC325392090F789255b9948Ab1659b797964) | Central registry and lifecycle manager for StakingVaults connected to the Lido protocol. Handles vault connection, minting/burning stETH against vault collateral, rebalancing, fee settlement, and bad debt management. [Learn more](/contracts/vault-hub/) | -| `PredepositGuarantee` | [`0xa5F55f3402beA2B14AE15Dae1b6811457D43581d`](https://hoodi.etherscan.io/address/0xa5F55f3402beA2B14AE15Dae1b6811457D43581d) | PredepositGuarantee (PDG) mitigates deposit frontrunning by requiring a node operator guarantee and validator withdrawal credentials proofs (EIP-4788) before activating staged deposits. [Learn more](/contracts/predeposit-guarantee/)| -| `LazyOracle` | [`0xf41491C79C30e8f4862d3F4A5b790171adB8e04A`](https://hoodi.etherscan.io/address/0xf41491C79C30e8f4862d3F4A5b790171adB8e04A) | Oracle adapter for stVaults. Stores per-vault reports, applies sanity checks, and forwards vault updates to VaultHub. [Learn more](/contracts/lazy-oracle/) | -| `OperatorGrid` | [`0x501e678182bB5dF3f733281521D3f3D1aDe69917`](https://hoodi.etherscan.io/address/0x501e678182bB5dF3f733281521D3f3D1aDe69917) | Registry for node operators, groups, and tier parameters that define share limits, reserve ratios, and fee schedules for stVaults. [Learn more](/contracts/operator-grid/) | - - - -### Deployed stVault addresses to be whitelisted -When an stVault is created (deployed), it includes two smart contracts by default: `StakingVault` (the core primitive) and `Dashboard` (an interface layer for the StakingVault that simplifies interaction). -You can find the addresses of these smart contracts at the bottom of the stVault main page (Dashboard): - -stVaults Web UI: Smart Contract addresses \ No newline at end of file diff --git a/run-on-lido/stvaults-legacy/tech-documentation/consolidation.md b/run-on-lido/stvaults-legacy/tech-documentation/consolidation.md deleted file mode 100644 index 71e643a49..000000000 --- a/run-on-lido/stvaults-legacy/tech-documentation/consolidation.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 🔁 Consolidations - -Stakers with validators already running may need to join stVaults. Validators in stVaults must have withdrawal credentials set to the Vault contract address. Instead of stopping existing validators, moving funds, and launching new ones, stakers can use the consolidation mechanism [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251). This makes it possible to migrate funds from their current validators to new validators whose withdrawal credentials point to the stVaults. - -This document provides step-by-step instructions for performing the process smoothly with our stVaults CLI. - -:::warning -Consolidation is irreversible. Once initiated, the process cannot be undone. -::: - -:::info -The consolidation mechanism only transfers the effective balance from source validators to target validators. Any rewards above the effective balance are automatically withdrawn to the source validator's withdrawal credentials during the consolidation process. -::: - -## 1. Setup stVaults CLI tool - -Use [these instructions](https://lidofinance.github.io/lido-staking-vault-cli/) to setup stVaults CLI. - -## 2. Preconditions - -- A fresh oracle report must be applied to the vault before consolidating. See the [Applying Oracle Reports](../operational-and-management-guides/applying-report-guide) for details. -- Grant `NODE_OPERATOR_FEE_EXEMPT_ROLE` to the address of your original validator's withdrawal credentials: - -
- using Command-line Interface - -First, discover the role hash: - -```bash -yarn start vo r roles -``` - -Then grant the role: - -```bash -yarn start vo w role-grant --roleAssignments '[{"account": "", "role": ""}]' -``` - -You can also use interactive mode: - -```bash -yarn start vo w role-grant -``` - -For detailed CLI options, see [vault operations documentation](https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations#role-grant). - -
-
- using stVaults Web UI - -1. Go to `https://stvaults.lido.fi/vaults//settings/permissions`. -2. Navigate to the "Node Operator Manager Permissions" section, "Node operator's sub-role for fee exemptions" item. -3. Add the address of your original validator's withdrawal credentials. - -
- -- Source validators - - withdrawal credentials must be `0x01` or `0x02` (`0x00` is not supported). - - withdrawal credentials must point to an address able to sign and execute transactions. - - must be active (i.e., not exiting or slashed). - - must be active for at least 256 epochs (`SHARD_COMMITTEE_PERIOD`) to be able to perform consolidation. - - must have no pending withdrawals in the queue. -- Target validators - - must have withdrawal credentials of type `0x02` equal to stVault's `withdrawalCredentials()` function result. - - must be active (i.e., not exiting or slashed). **For newly created validators, this means depositing at least 32 ETH (`MIN_ACTIVATION_BALANCE`) and waiting for activation.** - -:::note -You can check a validator's credentials or state at [beaconcha.in](https://beaconcha.in/validator/). -::: - -## 3. Prepare input data - -- A list of source pubkeys of validators that you want to consolidate from. -- A list of target pubkeys of validators that you want to consolidate to. -- The [Dashboard](/contracts/dashboard) contract address used to control the stVault. You can discover it via CLI: - ```bash - yarn start helpers find-dashboard-by-vault - ``` - For more details, see [additional helpers documentation](https://lidofinance.github.io/lido-staking-vault-cli/get-started/additional-helpers#find-dashboard-by-vault). -- To cover the consolidation fee costs, you'll need some amount of ETH. The exact amount depends on the number of public keys and the current state of the blockchain. You can determine the fee for a single consolidation request by calling the view function [`getConsolidationRequestFee`](/contracts/validator-consolidation-requests#getconsolidationrequestfee) on the [`ValidatorConsolidationRequests`](/contracts/validator-consolidation-requests) contract. The total amount required will be calculated as the number of consolidations multiplied by the fee per request. - -## 4. Run consolidation command - -All input data for consolidation requests undergoes two checks: off-chain in CLI and on-chain by our audited contract [`ValidatorConsolidationRequests`](/contracts/validator-consolidation-requests). Additionally, the calldata for the final request is formed on-chain, which brings an additional level of security. - ---- - -### Steps - -1. Configure WalletConnect [by the instruction](https://lidofinance.github.io/lido-staking-vault-cli/get-started/wallet-connect). -2. Create a JSON file with pubkeys in the following format: - -```json -{ - "target_pubkey_first": ["source_pubkey_first_group_01", "source_pubkey_first_group_02"], - "target_pubkey_second": ["source_pubkey_second_group_01", "source_pubkey_second_group_02"] -} -``` - -3. Run the command using the WalletConnect option: - -```bash -yarn start consolidation write consolidate-validators --file --wallet-connect --batch -``` - -- By default, stVaults CLI will execute consolidation requests using the `eth_sendTransaction` method, processing the transaction calls one by one. It will display a QR code or a link for WalletConnect, allowing you to sign the transactions in an external wallet client or in Safe, if you are using a multisig with WalletConnect. -- You can use the `--batch` flag (requires `--wallet-connect`) to bundle all consolidation requests and fee exemption adjustments into a single transaction using [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792) for more gas-efficient execution. -- If your wallet does not support batching with `EIP-5792`, the consolidation requests will fall back to individual transactions even with the `--batch` flag. - -:::info -The CLI automatically filters out inactive validators from the consolidation list and displays a warning for any removed validators. -::: - -For detailed information about consolidation command options, requirements, and error handling, see the [stVaults CLI documentation](https://lidofinance.github.io/lido-staking-vault-cli/commands/consolidation#consolidate-validators-consolidate). - -:::note -Alternatively, you can list pubkeys directly in the command as parameters: - -```bash -yarn start consolidation write consolidate-validators \ - --source_pubkeys "source_pubkey_first_group_01 source_pubkey_first_group_02, source_pubkey_second_group_01 source_pubkey_second_group_02" \ - --target_pubkeys "target_pubkey_first target_pubkey_second" \ - --wallet-connect -``` - -::: - -:::info[What happens after the request] -Once a consolidation request is processed on the consensus layer: - -1. **Exit is scheduled** — the source validator's `exit_epoch` is set. If many validators are exiting network-wide, the churn limit may delay the actual exit epoch. The source validator **earns rewards** while waiting. -2. **Source validator exits** — at `exit_epoch`, the source validator is excluded from active duties (attestations, block proposals)[^1]. The source validator **stops earning rewards**. - -[^1]: In rare cases, exited validators [may still be called for sync committee duties](https://ethresear.ch/t/sync-committees-exited-validators-participating-in-sync-committee/15634) if they were assigned before exit. Such validators should remain active for up to 256 epochs (`SHARD_COMMITTEE_PERIOD`) after exit to fulfill these duties. -3. **Withdrawability delay** — the source validator waits `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` (256 epochs, ~27 hours). **No rewards are earned** on this balance during the delay. -4. **Balance transfer** — the source validator's effective balance is moved to the target validator. Any excess above the effective balance is withdrawn to the source validator's withdrawal credentials. The target validator **starts earning rewards** on the combined balance. - ::: - -## 5. Post-consolidation checks - -### 5.1 Check consolidation request state - -Consolidation request transactions may succeed on the execution layer but fail on the consensus layer. - -- Navigate to: `https://beaconcha.in/validator/#consolidations`. -- Check the consolidation request status for each validator you consolidated to. - -### 5.2 Revoke NODE_OPERATOR_FEE_EXEMPT_ROLE role - -
- using Command-line Interface - -```bash -yarn start vo w role-revoke --roleAssignments '[{"account": "", "role": ""}]' -``` - -You can also use interactive mode: - -```bash -yarn start vo w role-revoke -``` - -For detailed CLI options, see [vault operations documentation](https://lidofinance.github.io/lido-staking-vault-cli/commands/vault-operations#role-revoke). - -
-
- using stVaults Web UI - -1. Go to `https://stvaults.lido.fi/vaults//settings/permissions`. -2. Navigate to the "Node Operator Manager Permissions" section, "Node operator's sub-role for fee exemptions" item. -3. Remove the withdrawal credentials address. - -
- -## Useful links - -- [ValidatorConsolidationRequests contract](/contracts/validator-consolidation-requests) -- [Dashboard contract](/contracts/dashboard) -- [stVaults Roles and Permissions](../features-and-mechanics/roles-and-permissions) -- [Applying Oracle Reports](../operational-and-management-guides/applying-report-guide) -- [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251) -- [stVaults CLI documentation](https://lidofinance.github.io/lido-staking-vault-cli/) -- [stVaults CLI consolidation command](https://lidofinance.github.io/lido-staking-vault-cli/commands/consolidation) diff --git a/run-on-lido/stvaults-legacy/tech-documentation/index.md b/run-on-lido/stvaults-legacy/tech-documentation/index.md deleted file mode 100644 index b5a003765..000000000 --- a/run-on-lido/stvaults-legacy/tech-documentation/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -sidebar_position: 4 ---- - -# 📚 Tech Documentation - -Technical references for stVaults architecture, integrations, and operational workflows. - -## In this section - -- [Integration overview](./integration-overview.md) -- [Technical Design and Architecture](./tech-design.md) -- [Consolidation: Migrate validators to the stVault](./consolidation.md) -- [Predeposit Guarantee](./pdg.md) diff --git a/run-on-lido/stvaults-legacy/tech-documentation/integration-overview.md b/run-on-lido/stvaults-legacy/tech-documentation/integration-overview.md deleted file mode 100644 index 8ff58b1ce..000000000 --- a/run-on-lido/stvaults-legacy/tech-documentation/integration-overview.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 🔌 Integration overview - -stVaults are Lido staking building blocks that allow creating custom staking solutions while still accessing unmatched stETH liquidity. This guide provides instructions for **managing** and **integrating** Staking Vaults (stVaults). It covers various interaction levels, from direct contract calls to using CLI tools and web interfaces, depending on requirements and preferred methods of fine-grained control. - -For a deeper technical dive, you can check out the [stVaults Technical Design and Architecture](https://hackmd.io/@lido/stVaults-design). - -:::tip 📣 **Leave feedback** -Trying to integrate with Lido V3 and stVaults? -Please share your thoughts through **[the short form](https://tally.so/r/3X9vYe)**. -::: - -## Architecture Overview - -![integration-overview](/img/stvaults/integration-overview.png) - -stVaults consist of the following components: - -- **[stVaults Web UI](#web-ui)**: A web interface interacting directly with the `Dashboard` contract and other stVaults-related contracts, providing a user-friendly experience for managing vaults and monitoring metrics. -- **[CLI (Command Line Interface)](#command-line-interface)**: A command-line tool interacting directly with the `Dashboard` contract and other stVaults-related contracts offering advanced management capabilities (deposits, generating proofs, per-vault oracle reports, etc.). ([GitHub Repository](https://github.com/lidofinance/lido-staking-vault-cli), [Documentation](https://lidofinance.github.io/lido-staking-vault-cli/)) -- **[Dashboard contract](#dashboard-contract)**: A management contract deployed together with the `StakingVault` contract, and assigned as the owner of the `StakingVault` contract by default. It provides granular management capabilities and introduces roles and permissions, allowing different actions to be managed by distinct roles. It also provides utility functions for minting/burning, performing deposits, and collecting Node Operator fees. -- **[StakingVault Contract](#stakingvault-contract)**: The core primitive contract representing the staking vault. Advanced use cases might include direct interaction with the `StakingVault` contract, which requires transferring ownership from the `Dashboard` contract. -- **[Predeposit Guarantee (PDG)](#predeposit-guarantee-pdg)**: The contract that mitigates deposit frontrunning vulnerabilities described in [LIP-5](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-5.md). It uses a mechanism distinct from the [Deposit Security Module](/contracts/deposit-security-module) adopted by **Lido Core**. It allows the Vault Owner and Node Operators to deposit validators with the vault's funds in a trustless manner. -- **Off-chain monitoring tools (can be used by the Node Operator):** - - **[Ethereum Validators Monitoring (EVM)](#ethereum-validators-monitoring-evm)**: Consensus layer validators monitoring bot that fetches Lido or Custom Users Node Operators keys from the Execution layer and checks their performance on the Consensus layer by the balance delta, attestations, proposes, sync committee participation. -- **[Ethereum Head Watcher](#ethereum-head-watcher)**: Bot that watches Ethereum head block, handles validator-related "events", and sends notifications through Alertmanager to a Discord channel. - -For contract APIs and addresses, see the [stVaults contracts reference](/contracts/vault-hub). - -## Integration and interacting layers - -### Web UI - -:::info -The Web UI covers nearly all routine stVault tasks for [Lido V3 testnet on Hoodi](/deployed-contracts/hoodi/). -For advanced or low-level features that haven’t yet been exposed in the interface, use the [CLI](#command-line-interface). -::: - -**URL**: -- Testnet on Hoodi: https://stvaults-hoodi.testnet.fi/ -- Mainnet: https://stvaults.lido.fi/ (will be available on [Phase 2 of the Rollout plan](https://research.lido.fi/t/lido-v3-design-implementation-proposal/10665/8)) - -**Goal**: Provide an easy-to-use interface for managing and monitoring stVaults via the Vault UI. - -**Steps**: - -1. Access the Vault Web UI and connect the wallet. -2. Create a vault and set up roles and permissions. -3. Supply/withdraw ETH, mint/repay stETH. -4. Control stVault Health factor and corresponding metrics, configure stVault settings. - -**Use case example**: - -- Individual and institutional stakers using the Web UI to perform operations, exploring vault performance, economy, fees, and efficiency. -- Prospecting vault owners examining node operator performance and vault efficiency before creating their own stVault. -- Anyone using the Web UI as an educational and analytical tool for understanding stVaults mechanics and economy. - -### Command-line interface - -**URL**: [GitHub Repository](https://github.com/lidofinance/lido-staking-vault-cli), [Documentation](https://lidofinance.github.io/lido-staking-vault-cli/) - -**Goal**: Manage stVaults via CLI for day-to-day and advanced operations as well as automation (deposits, generating/submitting proofs, per-vault oracle reports, etc.). - -**Steps**: - -1. Clone the GitHub repository and configure it according to the [CLI User Guide](https://lidofinance.github.io/lido-staking-vault-cli/get-started/configuration). -2. Deploy, configure vaults, assign roles, and manage staking operations. -3. Utilize commands for advanced maintenance. -4. Check-up the vault state via data provided by CLI. - -**Use case examples**: - -- Institutional integrator requiring automated and scriptable staking management. -- Node Operator using the CLI to initiate staking operations and monitor staking performance, as well as predeposit, prove, and top-up validators via Predeposit Guarantee (PDG). -- Protocols integrating with stVaults and running integration. - -### Dashboard contract - -**URL**: [GitHub Repository](https://github.com/lidofinance/core/blob/feat/vaults/contracts/0.8.25/vaults/dashboard/Dashboard.sol) - -**Goal**: Provide a feature-rich straightforward UX layer for staking vault and `VaultHub` and additional accounting for Node Operator fee. - -**Steps**: - -1. Call `VaultFactory` to create a `StakingVault` contract and a `Dashboard` contract assigned as an owner of the Vault contract. -2. Define roles and permissions on the `StakingVault` creating, or later via the `Dashboard` contract. -3. Interact with the `Dashboard` contract for high-level operations. -4. Use role-specific methods via the `Dashboard` contract to interact with the `StakingVault` contract. - -**Use case example**: - -- Granular permissions for staking vault operations and Node Operator fee claiming. -- Structured product integrating stVaults for staking operations with granular control. - -### StakingVault contract - -**URL**: [GitHub Repository](https://github.com/lidofinance/core/blob/feat/vaults/contracts/0.8.25/vaults/StakingVault.sol) - -**Goal**: Directly manage a `StakingVault` contract by transferring its ownership from the `Dashboard` contract to reduce operations gas costs (**advanced integrations**). - -> If vault ownership is changed to interact with the vault directly, it’s no longer possible to use other Lido stVaults infrastructure mechanisms to manage the vault. In this case, direct interaction with Lido core protocol via the Vault Hub contract is required. - -**Steps**: - -1. Call `VaultFactory` to create a `StakingVault` contract and a `Dashboard` contract. -2. Transfer ownership from the `Dashboard` contract to the desired address. -3. Use smart contract calls to configure, supply, withdraw, and manage other operations. -4. Monitor contract status directly via blockchain explorers or custom tools. - -**Use case example**: - -- Institutional users with a dedicated infrastructure for contract interaction who require maximum control over staking operations. -- Structured product integrating `StakingVault` directly to reduce operations gas costs and use own infrastructure. - -### Predeposit Guarantee (PDG) - -**URL**: [Technical details](https://hackmd.io/@lido/stVaults-design?stext=5138%3A160%3A0%3A1744277214%3A66cxZj); [GitHub Repository](https://github.com/lidofinance/core/blob/feat/vaults/contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol), [PDG user guide](./pdg) - -**Goal**: Prevent deposit frontrunning enabled by vulnerabilities described in [LIP-5](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-5.md). PDG secures the Vault Owner's ETH deposits to validators from front-running by the Node Operator or third parties. One of the key advantages is the separation of finances between the Vault Owner and the Node Operator. - -**How to use:** - -1. Create and configure a vault through any convenient interface (contracts, CLI, or UI). -2. Predeposit guarantee contract enables three main use cases: - 1. Full-cycle proof of validators through PDG to enable a non-custodial depositing mechanism, using the guarantee ETH as collateral ([read more](./pdg#full-cycle-trustless-path-through-pdg)). - 2. PDG shortcut that allows skipping the predepositing steps and depositing up to 2048 ETH to a validator in one transaction, with optional later association of the validator with the vault by proving it through PDG. Applicable when there is unconditional trust between the Node Operator and the Vault Owner ([read more](./pdg#pdg-shortcut)). - 3. Adding existing validator to Vault from external staking infrastructure as an advanced integration use-case. - -### Off-chain monitoring tools - -#### **Ethereum Validators Monitoring (EVM)** - -**Where**: [GitHub Repository](https://github.com/lidofinance/ethereum-validators-monitoring) - -**Goal**: Off-chain track the status and performance of Ethereum validators used in stVaults. It helps detect inactivity, monitor effectiveness, and identify anomalies in validator operations. - -**How to use:** - -- Clone the repository from GitHub. -- Install dependencies and set up the environment. -- Run the monitoring tool to get validator status. -- Integrate the output with alerting or dashboards. - -#### **Ethereum Head Watcher** - -**Where**: [GitHub Repository](https://github.com/lidofinance/ethereum-head-watcher) - -**Goal**: Off-chain monitor Ethereum chain head updates to detect delays, stalls, or reorgs. It is used to ensure timely block processing and head finality, which are critical for the stability of services like stVaults. - -**How to use:** - -- Clone the repository from GitHub. -- Install dependencies and configure environment variables. -- Run the watcher to observe head progression. -- Connect it to alerting or monitoring systems if needed. diff --git a/run-on-lido/stvaults-legacy/tech-documentation/pdg.md b/run-on-lido/stvaults-legacy/tech-documentation/pdg.md deleted file mode 100644 index c530994df..000000000 --- a/run-on-lido/stvaults-legacy/tech-documentation/pdg.md +++ /dev/null @@ -1,468 +0,0 @@ ---- -sidebar_position: 4 ---- - -# 🛡️ Predeposit Guarantee - -This user guide explains how to use the Predeposit Guarantee contract as part of the stVaults staking infrastructure. - -The Predeposit Guarantee (PDG) contract mitigates deposit frontrunning vulnerabilities outlined in [LIP-5](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-5.md). It disincentivizes frontrunning by having the Node Operator post an economic guarantee of honest behavior, which is proven/disproven via [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788). This mechanism is distinct from the [Deposit Security Module](/contracts/deposit-security-module) used by Lido Core. - -The PDG enables Node Operators to deposit validators using vault funds in a trustless manner. - -:::info -stVaults are using [`0x02-type`](https://eips.ethereum.org/EIPS/eip-7251) withdrawal credentials for deposits. -Therefore stVaults can utilize large validators (depositing up to 2048 ETH per single validator without losing efficiency). -::: - -## Resources - -- [Technical details](https://hackmd.io/@lido/stVaults-design#36-PredepositGuarantee) -- [GitHub Repository](https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol) -- [StVaults Command-line Interface](https://github.com/lidofinance/lido-staking-vault-cli) -- [StVaults CLI Docs](https://lidofinance.github.io/lido-staking-vault-cli/) - -## Deposit Data Generation - -Node Operators should generate deposit data with the following specifications for stVaults: - -- **Withdrawal credentials**: `0x02-type` format pointing to the stVault address (`0x02` + 30 bytes of zeros + stVault address) -- **Amount for predeposit**: 1 ETH (for the initial predeposit phase) - -Additional deposits may be made in any amount up to the validator’s remaining balance. Deposit data is only necessary for validator proof and is not needed for subsequent top-ups. - -:::tip **For Hoodi testnet only** -You can use this tool for generating deposit data: [Depositor](https://github.com/tamtamchik/depositor) -::: - -## PDG Flows - -### Full-cycle trustless path through PDG - -Advantages: - -- **Non-custodial depositing mechanism** using the Node Operator’s (or guarantor’s) provided ETH guarantee as collateral. -- **Separation of ETH funds** between the Vault Owner and the Node Operator. -- A depositing mechanism **that does not affect key stVaults metrics** — Total Value, stETH minting capacity, or Health Factor. This means ETH can be deposited to validators through PDG even when the stETH minting capacity is fully utilized. - -Use cases enabled by the full-cycle trustless path through PDG: - -- Direct top-ups of proved validators with ETH from the stVault Balance. -- Keys rotation even when the stETH minting capacity utilization is close to 100%. -- Leveraged staking through lending markets using a flash loan. - -![Full-cycle trustless](/img/stvaults/pdg_main_flow.png) - -Steps: - -1. The Vault Owner supplies 2048 ETH (minimum 32 ETH required to activate a validator) to the vault. - - Method called: `Dashboard.fund()` with ETH transfer (`payable`). - - Caller must have the `FUND_ROLE` role. - -
- using Command-line Interface - - ```bash - yarn start vo write fund -v - ``` - -
- -2. **(Optional)** The Node Operator assigns a `Guarantor` address that will provide a 1 ETH guarantee. _This allows the Node Operator to delegate guarantees to an arbitrary hot account while keeping the Node Operator private key safe in cold storage._ - - The default `Guarantor` is the Node Operator. - - Method called: `PredepositGuarantee.setNodeOperatorGuarantor(newGuarantor)`. - - Caller must be the `StakingVault.nodeOperator` address. - -
- using Command-line Interface - - ```bash - yarn start deposits write set-no-guarantor - # where is the address that will act as the Guarantor - ``` - -
- -3. **(Optional)** The Node Operator assigns a `Depositor` address that will deposit and top up validators with ETH from the stVault balance. _This allows the Node Operator to delegate deposits to an arbitrary hot account while keeping the Node Operator private key safe in cold storage._ - - The default `Depositor` is the Node Operator. - - Method called: `PredepositGuarantee.setNodeOperatorDepositor(newDepositor)`. - - Caller must be the `StakingVault.nodeOperator` address. - -
- using Command-line Interface - - ```bash - yarn start deposits write set-no-depositor - # where is the address that will act as the Depositor - ``` - -
- -4. The `Guarantor` tops up 1 ETH to the PDG contract, specifying the Node Operator's address. This serves as the predeposit guarantee collateral. - - Method called: `PredepositGuarantee.topUpNodeOperatorBalance(nodeOperator)` with ETH transfer. - - Caller must be specified as the `Guarantor` in the PredepositGuarantee contract. - -
- using Command-line Interface - - ```bash - yarn start deposits write top-up-no 1 -v - # The node operator address is derived from the vault contract - ``` - -
- -5. The `Depositor` generates validator keys and predeposit data. -
- using Command-line Interface - - ```bash - # Verify BLS signature and deposit data - yarn start pdg-helpers verify-predeposit-bls '' -a - - # Compute the deposit data root to verify it matches your generated data - yarn start pdg-helpers compute-deposit-data-root - ``` - - `` format (amount in gwei): - - ```json - [ - { - "pubkey": "0x...", - "signature": "0x...", - "amount": "1000000000", - "deposit_data_root": "0x..." - } - ] - ``` - -
- -6. The `Depositor` predeposits 1 ETH from the vault balance to the validator via the PDG contract. - - - Method called: `PredepositGuarantee.predeposit(stakingVault, deposits, depositsY)`. - - Caller must be the `Depositor` in the PredepositGuarantee contract. - - As a result: - - - 6.1. The PDG locks 1 ETH from the Node Operator's guarantee collateral in the PDG. - - 6.2. 31 ETH on the stVault balance is staged as Activation Deposit (expecting to be deposited to the validator later). - - 6.3. 1 ETH is deposited to validator. - -
- using Command-line Interface - - ```bash - yarn start deposits write predeposit '' -v - ``` - - `` format (amount in gwei): - - ```json - [ - { - "pubkey": "0x...", - "signature": "0x...", - "amount": "1000000000", - "deposit_data_root": "0x..." - } - ] - ``` - - After submitting, wait for the validator to appear on the Beacon Chain, then monitor its status: - - ```bash - # Check validator on the Consensus Layer - yarn start pdg-helpers validator-info - - # Check validator status in the PDG contract - yarn start deposits read validator-status - ``` - -
- -7. The `Depositor` proves the validator's appearance on the Consensus Layer to the PDG contract with the withdrawal credentials corresponding to the stVault's address, activates the validator, and (optionally) performs an extra top-up. - - - Method called: `PredepositGuarantee.proveWCActivateAndTopUpValidators(witness, amounts)`. - - Caller must be the `Depositor` in the PredepositGuarantee contract. - - As a result: - - - 7.1. Upon successful verification, 1 ETH of the Node Operator's guarantee collateral is unlocked from the PDG balance — making it available for withdrawal or reuse for the next validator predeposit. - - 7.2. 31 ETH is deposited to validator from the amount that was Staged on the stVault balance. - - 7.3. (Optional) extra ETH is deposited on validator, if extra top up was selected. - -
- using Command-line Interface - - ```bash - # Prove and activate only (31 ETH activation deposit, no extra top-up): - yarn start deposits write prove-and-activate -i - - # Or prove, activate AND top up in one transaction (combines steps 7 and 9): - yarn start deposits write prove-and-top-up -v - ``` - -
- -8. **(Optional)** The `Guarantor` withdraws the 1 ETH from the PDG contract or retains it for reuse with future validators. - - Method called: `PredepositGuarantee.withdrawNodeOperatorBalance(nodeOperator, amount, recipient)`. - - Caller must be the `Guarantor` in the PredepositGuarantee contract. - -
- using Command-line Interface - - ```bash - yarn start deposits write withdraw-no-balance 1 -v -r - # The node operator address is derived from the vault contract - ``` - -
- -9. The `Depositor` makes a top-up deposit of the remaining 2016 ETH from the vault balance to the validator through the PDG. - - - Method called: `PredepositGuarantee.topUpExistingValidators(Array topUps)`. - - Caller must be the `Depositor` in the PredepositGuarantee contract. - - As a result: - - - 9.1. 2016 ETH is deposited on validator. - -
- using Command-line Interface - - ```bash - yarn start deposits write top-up-existing-validators '' -v - ``` - - `` format (amount in gwei): - - ```json - [ - { - "pubkey": "0x...", - "amount": "2016000000000" - } - ] - ``` - -
- - :::note - Skip this step if you already used `prove-and-top-up` in step 7 with the full top-up amount. - ::: - -### PDG shortcut - -This mechanism allows one to bypass the predeposit step, enabling a one-transaction direct deposit of up to 2048 ETH (as per [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251)) to the validator without using PDG. The validator can be linked to the vault after the deposit by submitting proof through the PDG contract. - -Advantages: - -- Fewer actions, lower gas fees. It's possible to deposit 2048 ETH in one transaction. -- No mandatory requirement to prove validators if there are no plans to use top-up further. - -Cons: - -- This approach requires mutual off-chain trust between the Node Operator and the Vault Owner. -- This mechanism reduces stVault Total Value until validator activation **as reported by the oracle**. -- Requires unlocked ETH on the stVault Balance to deposit (i.e. not possible when utilization ratio is close to 100%). - -![Shortcut-pdg](/img/stvaults/pdg-shortcut.png) - -Steps: - -1. The Vault Owner supplies ETH to the vault but does not mint against it. - - - Method called: `Dashboard.fund()` with ETH transfer (`payable`). - - Caller must have the `FUND_ROLE` role (or be its admin). - -
- using Command-line Interface - - ```bash - yarn start vo write fund -v - ``` - -
- -2. The Vault Owner gives the Node Operator an explicit permission to bypass PDG by setting the appropriate PDG policy. - - - Method called: `Dashboard.setPDGPolicy(PDGPolicy)`. - - Caller must have the `DEFAULT_ADMIN_ROLE` role (or be its admin). - - PDG Policies: - - - `STRICT` (Default): deposits require the full PDG process. - - `ALLOW_PROVE`: allows proving unknown validators to PDG (but not unguaranteed deposits). - - `ALLOW_DEPOSIT_AND_PROVE`: allows both unguaranteed deposits (bypassing the predeposit requirement) and proving unknown validators. - -
- using Command-line Interface - - ```bash - yarn start contracts dashboard write set-pdg-policy ALLOW_DEPOSIT_AND_PROVE - ``` - - To check the current policy at any time: - - ```bash - yarn start contracts dashboard read pdg-policy - ``` - -
- -3. **(Optional)** The Node Operator Manager grants the necessary roles to the address that will perform unguaranteed deposits and proving. By default, the Node Operator Manager can perform unguaranteed deposits. In this guide, we assume both roles are granted to the same address referred to as `Depositor`. - - - Method called: `Dashboard.grantRole(role, account)` for each role. - - Caller must have the `NODE_OPERATOR_MANAGER_ROLE` role. - - Roles to grant: - - `NODE_OPERATOR_UNGUARANTEED_DEPOSIT_ROLE` — allows calling `unguaranteedDepositToBeaconChain()` - - `NODE_OPERATOR_PROVE_UNKNOWN_VALIDATOR_ROLE` — allows calling `proveUnknownValidatorsToPDG()` - -
- using Command-line Interface - - ```bash - # Runs interactively and will prompt for the role and the recipient account address. - # Roles to grant to the Depositor: - # - NODE_OPERATOR_UNGUARANTEED_DEPOSIT_ROLE - # - NODE_OPERATOR_PROVE_UNKNOWN_VALIDATOR_ROLE - yarn start vo write role-grant -v - ``` - -
- -4. **(Optional)** The Node Operator assigns a `Depositor` address in the PDG contract that will be authorized to top up validators via PDG after they are proven. By default, the Node Operator is the `Depositor`. - - - Method called: `PredepositGuarantee.setNodeOperatorDepositor(newDepositor)`. - - Caller must be the Node Operator address (as registered in the StakingVault via `nodeOperator()`). - -
- using Command-line Interface - - ```bash - yarn start deposits write set-no-depositor - # where is the address that will act as the Depositor - ``` - -
- -5. The `Depositor` generates validator keys and deposit data with: - - - Withdrawal credentials in `0x02-type` format pointing to the stVault address (`StakingVault.withdrawalCredentials()`). - - Deposit amount must not bring the validator balance over 2048 ETH. - - Use an external validator key generation tool. Verify deposit data before proceeding: - -
- using Command-line Interface - - ```bash - # Compute and verify the deposit data root - yarn start pdg-helpers compute-deposit-data-root - ``` - -
- -6. The `Depositor` performs a deposit in the specified amount from the vault balance to the validator via the Dashboard contract. - - - Method called: `Dashboard.unguaranteedDepositToBeaconChain(deposits)`. - - Caller must have the `NODE_OPERATOR_UNGUARANTEED_DEPOSIT_ROLE` role (or be its admin). - - As a result: - - - 6.1. ETH is withdrawn from the stVault's withdrawable balance. - - 6.2. stVault Total Value is reduced by the deposit amount until the validator appears in the Beacon Chain state AND is included in a subsequent Oracle report. - - 6.3. ETH is deposited to the validator via the Ethereum Deposit Contract. - -
- using Command-line Interface - - ```bash - yarn start deposits write unguaranteed-deposit '' -v - ``` - - `` format (amount in gwei): - - ```json - [ - { - "pubkey": "0x...", - "signature": "0x...", - "amount": "32000000000", - "deposit_data_root": "0x..." - } - ] - ``` - -
- -7. The Oracle report includes the new validator's balance; stVault Total Value increases by the deposit amount. - -
- using Command-line Interface - - ```bash - # Monitor vault metrics while waiting for the oracle report: - yarn start vo read overview -v - ``` - -
- -8. **(Optional)** The `Depositor` proves the validator's appearance on the Consensus Layer to enable future top-ups via PDG. If the validator has max effective balance (2048 ETH), there is no need to prove it, as it cannot be topped up further. - - - Method called: `Dashboard.proveUnknownValidatorsToPDG(witnesses)`. - - Caller must have the `NODE_OPERATOR_PROVE_UNKNOWN_VALIDATOR_ROLE` role (or be its admin). - - As a result: - - - 8.1. The validator transitions from `NONE` to `ACTIVATED` stage in PDG. - - 8.2. The validator is now registered in PDG and can receive top-ups via `topUpExistingValidators()`. - -
- using Command-line Interface - - ```bash - # Check validator index if needed: - yarn start pdg-helpers validator-info - - # The CLI fetches the beacon state witness for the given validator index automatically - yarn start contracts dashboard write prove-unknown-validators-to-pdg - ``` - -
- -9. **(Optional)** The `Depositor` makes a top-up deposit from the vault balance to the validator through PDG. - - - Method called: `PredepositGuarantee.topUpExistingValidators(topUps)`. - - Caller must be the address set as `Depositor` in the PDG contract. - - Top-up amount must not bring the validator balance over 2048 ETH. - - As a result: - - - 9.1. The specified ETH amount is deposited to the validator from the stVault balance. - -
- using Command-line Interface - - ```bash - yarn start deposits write top-up-existing-validators '' -v - ``` - - `` format (amount in gwei): - - ```json - [ - { - "pubkey": "0x...", - "amount": "1000000000" - } - ] - ``` - -
- -:::tip 📣 **Leave feedback** -Feel free to drop your thoughts about PDG and Lido V3 through **[this simple form](https://tally.so/r/3X9vYe)**. -::: diff --git a/run-on-lido/stvaults-legacy/tech-documentation/tech-design.md b/run-on-lido/stvaults-legacy/tech-documentation/tech-design.md deleted file mode 100644 index 8e06a071f..000000000 --- a/run-on-lido/stvaults-legacy/tech-documentation/tech-design.md +++ /dev/null @@ -1,715 +0,0 @@ ---- -sidebar_position: 2 ---- - -# 🏗️ Technical Design and Architecture - -## 1. Abstract - -Lido Staking Vaults (stVaults) are modular primitives that connect stakers, node operators, and protocols — enabling them to define custom fee structures, tailor validator configurations, and fine-tune risk/reward. This flexibility is achieved without compromising decentralization, security, or access to stETH liquidity. - -## 2. Design - -### 2.1 Goals - -StVaults are designed to: - -1. Enable customizable risk-reward profiles for liquid staking while preserving stETH's stability and fungibility. -2. Improve alignment with node operators who wish to onboard clients and actively participate in the Lido protocol. -3. Support the development of structured staking products and deeper protocol integrations. - -These goals are built on the vision outlined in [Hasu's 2nd GOOSE voted-in proposal](https://snapshot.box/#/s:lido-snapshot.eth/proposal/0xeedef9fea3d782f192410768cabaf6974da40ef36e1d22c7f8fff5fd4cfc7a59), establishing a foundational layer for diverse staking product lines. - -### 2.2 Principles - -The introduction of stVaults brings major changes to the existing Lido core pool protocol contracts (hereafter referred to as **Lido Core**). To ensure protocol stability, it's essential to define the foundational constraints that remain unchanged: - -1. StVaults users do not negatively affect stETH users: - - StVaults do not negatively affect stETH users' APR - - Slashing risk consequences are contained within the node operator group of staking vaults up to the level agreed by the DAO -2. StVaults have a set reserve ratio that determines the quantity of stETH that can be minted based on ETH provided, and can only be changed by the DAO -3. The impact of possible reallocation of stake between Lido Core and stVaults is contained and manageable -4. StETH solvency - all existing stETH can be converted into ETH at a 1:1 ratio - -So, it remains the key priority to maintain the stability and security of the Lido Core and the whole Lido staking infrastructure. - -## 3. Architecture - -The Lido Vaults platform comprises the following contracts: - -- **StakingVault**: Manages individual staking positions and holds assets for validators. -- **VaultHub**: Serves as the central registry and coordination point between the vaults platform and Lido Core. -- **LazyOracle**: Verifies reports from the oracle network and forwards individual vault updates to VaultHub. -- **OperatorGrid**: Maintains a node operator registry and manages vaults' minting parameters. -- **PredepositGuarantee**: Ensures validator deposit security. -- **VaultFactory**: Deploys verified (allowed to be connected to VaultHub) vault instances. -- **Dashboard**: An optional contract that provides node operator fee accounting and a UX-friendly interface for a StakingVault. - -See the [stVaults contracts reference](/contracts/vault-hub) for per-contract APIs. - - -### 3.1 StakingVault - -The StakingVault contract is a 0x02-type withdrawal credentials target and a fundamental building block of the Lido Vaults platform. It represents an isolated staking position managed by a single **owner** and serviced by a single **node operator**. When connected to Lido, the vault can be used as collateral for minting stETH. - -With a StakingVault, the owner can: - -- Stake their funds directly with their preferred node operator without giving up custody; -- Tap into various block proposing and validation flavors; -- Mint stETH backed by the StakingVault's total value; and -- Build structured products by integrating protocols and risk curators. - -:::important -A staking vault is a valid **0x02-type** withdrawal credentials target and supports [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251). Any **0x01-** or **0x02-type** validator can have its balance transferred to a vault validator via the execution-layer consolidation request. A **0x00-type** validator will first have to migrate to **0x01-type** credentials. -::: - -![Primer diagram](/img/stvaults/tech-design/primer-diagram.png) - -#### Vault Entities - -##### Owner - -The owner is the administrative account with the most power in the vault. The owner can: - -- fund ETH to the vault, -- withdraw ETH from the vault, -- pause and resume beacon-chain deposits, -- request validator exits, -- trigger [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) validator withdrawals, -- change the depositor, -- irreversibly ossify the vault implementation to opt out of proxy upgrades, -- transfer the ownership to another account via the [2-step ownership model](https://docs.openzeppelin.com/contracts/5.x/api/access#Ownable2Step). - -When a vault connects to the Lido protocol, VaultHub is set as the vault’s technical owner, serving as an intermediate layer that enforces collateral locks to protect the stETH minted against the vault. The vault’s factual owner is recorded inside VaultHub. Once the vault disconnects from the protocol, VaultHub releases control and restores ownership to that recorded owner, preserving the non-custodial nature. - -##### Node operator - -The node operator address represents the party that runs the validators associated with the vault. This address is set upon initialization of the vault and cannot be changed. - -:::important -It is strongly recommended to use a multisignature account (e.g., Gnosis Safe) to avoid losing access to this account. -::: - -Because validator withdrawal credentials are hard-coded to the vault (0x02-type pointing back to the contract), all consensus rewards and exited balances flow into the StakingVault automatically; the operator never takes custody of ETH. - -The node operator: - -- is expected to perform voluntary exits of the validators as signalled by the owner. -- can forcefully eject vault-associated validators via [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002). - -##### Depositor - -The depositor address is the only party allowed to perform deposits to the beacon chain consuming staged balance resident in the vault. Due to the frontrunning vulnerability (see [3.6: PredepositGuarantee](#36-predepositguarantee)), this responsibility is extracted into a separate role controlled by the vault owner. When connected to the Lido protocol, the depositor must be set to PredepositGuarantee, a specialized contract that mitigates deposit frontrunning. - -#### Staged balance - -:::note -Staged balance is a mechanism **only** used as part of the PredepositGuarantee contract's predeposit-based deposit process. -::: - -The vault depositor controls the vault's **staged balance** counter that reserves ETH for validator activations and cannot be withdrawn. Unstaging ETH makes this ETH available for withdrawal again. This staging mechanism ensures the vault's commitment to activating the validator. Staging enforces a strict invariant: every predeposit of 1 ETH must be paired with 31 ETH staged for activation. This guarantees that the validator can always be topped up to the required 32 ETH, the minimal balance for validator activation. Without this rule, a vault could spawn many 1-ETH validators that never activate, leaving funds locked on the beacon chain that cannot be withdrawn for protocol obligations. - -**StakingVault source code**: https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/StakingVault.sol - -### 3.2 VaultHub - -VaultHub is the central coordination contract of the Lido Vaults platform. It maintains the registry of connected **StakingVaults**, enforces collateralization constraints, mints and burns stETH against per-vault total values, and tracks vault obligations. - -When a StakingVault is connected to VaultHub, the latter: - -- assumes technical ownership of that vault (via the 2-step pattern) and escrows the **CONNECT_DEPOSIT** (1 ETH); -- records static connection parameters (share limit, reserve ratio, fees) supplied by **OperatorGrid**; -- tracks dynamic state (total value, locked ETH, liability shares, obligations—fee accrued and redemptions if applicable) using reports from **LazyOracle**; and -- exposes a control surface for the vault owner to fund, withdraw, mint, burn, rebalance, pause beacon-chain deposits, request validator exits, and settle obligations. - -The **vault owner**: -- retains ownership of the underlying StakingVault through VaultHub; -- is authorized to fund, withdraw, mint, burn, manage validators, and settle obligations; -- may transfer factual ownership to another owner without disconnecting the vault. - -_Diagram. VaultHub interactions_ -![Simplified contract structure](/img/stvaults/tech-design/simplified-contract-structure.png) - -**VaultHub source code:** https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/VaultHub.sol - -#### Vault accounting - -Each StakingVault has two important parameters that define its state: **total value** and **locked**. - -- **total value**: The estimated total of all the vault's validator balances plus any ETH held by the vault contract itself. -- **locked**: The amount of ETH on this vault that is _blocked_ from withdrawal. This amount backs the stETH tokens minted via this stVault. - -To control stETH minting, VaultHub tracks these parameters for each stVault: - -- **Liability**: The amount of stETH shares minted against the vault (as in, liability towards Lido Core). -- **Reserve ratio (RR)**: A portion of the vault's total value locked as an additional reserve (safety buffer) for minted stETH (e.g., if reserve ratio is 30%, with a total value of 100 ETH, 30 ETH must be reserved, which means the vault can mint 70 stETH max). The maximum possible reserve ratio is 99.99%. -- **Force rebalance threshold (FRT)**: When the reserve drops below this threshold, the vault is considered unhealthy and is subject to **force-rebalancing**. FRT must be at least 0.1% lower than RR, e.g. if RR is 30%, FRT must be 29.9% or smaller. -- **Share limit**: The absolute flat cap on stETH shares that a stVault can mint. -- **Obligations**: the health obligation, stETH redemption requests, and Lido fees. - -If the vault's locked amount breaches FRT, the vault is considered unhealthy and: - -- cannot mint stETH -- cannot withdraw ETH -- cannot deposit new validators -- is limited to full validator withdrawals only -- and is subject to permissionless force-rebalancing. - -:::important -Thanks to [Pectra's EIP-6110](https://eips.ethereum.org/EIPS/eip-6110) and PredepositGuarantee, valid pending deposits contribute to `totalValue`, which allows seamless minting without waiting for the entry queue to clear the deposit. -::: - -_Diagram. Vault totalValue breakdown_ -![Vault totalValue breakdown](/img/stvaults/tech-design/vault-totalvalue-breakdown.png) - -#### Liquidity - -Unlike Lido Core, which mints stETH at a 1:1 ratio to supplied ether, Lido Vaults mints stETH at a more conservative ratio. A lower ratio effectively means that the StakingVault must maintain a reserve margin (**Reserve Ratio** or **RR**) determined by risk parameters and limits. - -Upon minting stETH, the corresponding amount of ether (plus some reserve due to RR) is **locked** as collateral on the StakingVault, i.e. cannot be withdrawn. The system tracks [stETH shares](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics) (**liabilityShares**) minted for each StakingVault and updates the **locked** amount (denominated in ether) on the StakingVault according to the stETH rebase. To unlock ether for withdrawal, the StakingVault must burn the outstanding amount of stETH (i.e., repay stETH). - -##### Example - -Given: - -- **Reserve Ratio**: 20% (2000 BP) -- **Force Rebalance Threshold**: 15% (1500 BP) - -**Stage 1 - Initial State (Healthy):** - -- Total value: **100 ETH** -- Liability: **0 stETH** -- Reserve: **100 ETH** (100% of total value reserved > FRT 15%) -- Status: Can mint - -**Stage 2 - Minted StETH (Healthy):** - -- Total value: **100 ETH** -- Liability: **80 stETH** -- Reserve: **20 ETH** (20% of total value reserved > FRT 15%) -- Status: Healthy but can't mint anymore - -**Stage 3 - Slashing:** - -- Total value drops to: **90 ETH** -- Liability: **80 ETH** -- Reserve: **10 ETH** (11.1% of total value reserved < FRT 15%) -- Status: Unhealthy, subject to force rebalance - -#### Locked - -The locked amount is the total ETH in a vault that cannot be withdrawn. It represents the collateral backing the vault's stETH liability plus reserve. This locked amount ensures the vault remains overcollateralized and can absorb penalties without immediately creating bad debt. The locked amount consists of **stETH liability** and **reserve**, i.e., `locked = liability + reserve`. The reserve itself is derived as the greater of the reserve calculated from the Reserve Ratio and the minimal reserve. - -The minimal reserve is the absolute floor for how much collateral must stay locked in a vault, regardless of how much liability exists. The minimal reserve is calculated as the greater of the **connect deposit** and **slashing reserve**. - -- **1 ETH Connect Deposit**. Vault creation requires at least 1 ETH to be in the connecting vault. This mandatory connect deposit acts as an anti-sybil mechanism that prevents the creation of spam vaults that would burden the oracle network. The VaultHub verifies that sufficient ETH is present on the vault's balance before proceeding with vault connection, locks this deposit during setup, and keeps it locked for the duration of the vault's connection to VaultHub; it may be used to pay out Lido fees. The connect deposit cannot be used to mint stETH against. -- **Slashing reserve**. Applicable for vaults of a node operator with validators undergoing slashing - an extra chunk of ETH that must remain locked in the event of slashing until the oracle proves that the vault's validators are no longer at risk of being additionally penalized due to the beacon chain's [associated slashing mechanism](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/). The oracles calculate the reserve off-chain (based on the validator set, time-at-risk, and any slashable offenses it detects) and publish the figure in every report. When the report is applied, VaultHub locks at least this reserve on the vault until the validators are cleared and no additional correlation penalties have been applied. - -So the final calculation for **locked** is as follows: -$$ -locked = liability + \max(calculatedReserveFromRR, \max(connectDeposit, slashingReserve)) -$$ - -_Diagram. Locked amount breakdown_ -![StakingVaults Diagrams](/img/stvaults/tech-design/stakingvaults-diagrams.png) - -#### Vault obligations - -Obligations are the record of everything a StakingVault _owes_ to the Lido protocol and thus impose a block on the vault balance equal to the pending obligations. VaultHub tracks three types of obligations. - -##### 1. Health obligation - -Nominated in stETH shares, the health obligation is the amount of liability shares that must be force-rebalanced to restore the vault's health. The health obligation arises automatically when collateralization drops below the health threshold as a result of validator penalties, slashing, or underperformance compared to stETH APR. The health obligation has the **highest settlement priority** over the rest of the obligations. - -:::warning -Force-rebalancing is a **punishing** operation, so it is strongly recommended to restore health in more efficient ways like repaying stETH or funding the vault when approaching FRT. -::: - -##### 2. Redemptions - -Nominated in stETH shares, redemptions represent the amount of liability that must be rebalanced or burned to support Lido Core withdrawals. In a rare scenario where the Lido Core pool is depleted and needs liquidity for its withdrawal queue, the protocol retains the right to issue a redemption obligation to an eligible vault, which ought to be settled by rebalancing or burning shares. Redemption settlement writes off the corresponding liability amount from the vault and supplies the Core pool with ETH to process withdrawals. Redemptions have the **second priority**, meaning the protocol first restores health of the vault and only then settles any redemptions. - -:::important -Issued redemptions **do not increase** the vault's liability. Redemptions can be thought of as a portion of the vault's existing liability that must be burned or rebalanced, i.e. if the vault does not have any liability, the protocol cannot issue a redemption against the vault. -::: - -##### 3. Lido fees - -Nominated in ETH, **Lido fees** - the combined **infra**-, **liquidity**- and **reservation**-fees - are the Lido protocol service fees. These fees accrue continuously on each oracle report, which supplies an updated cumulative-fee counter. VaultHub tracks the settled-fees counter; thus, the delta between cumulative fees and settled fees is considered **unsettled fees**. Lido fees have the **lowest priority**, i.e., are settled only if the vault is healthy and has no redemptions assigned. Lido fees are settled permissionlessly via a dedicated function in VaultHub. - -Any outstanding obligations on a vault: - -- limit withdrawals from the vault by the amount required to cover obligations; -- reduce minting capacity by the amount required to cover obligations; -- pause beacon chain deposits while the vault is unhealthy, has redemptions to cover, or has unsettled fees greater than 1 ETH. This pause prevents the vault from continuously depositing ETH to the consensus layer and avoiding obligation settlement; -- reject attempts to disconnect from VaultHub. - -_Obligations cheatsheet_ - -| Obligation | Priority | Nominated in | Description | Accrual | Settlement | -| ----------- | -------- | ------------ | ---------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| Health | 1 | stETH shares | Liability to reduce to restore the vault's health | Arise automatically when health drops | Rebalancing. Highly advised to burn stETH or fund the vault before approaching FRT to avoid punishing force-rebalancing | -| Redemptions | 2 | stETH shares | Liability to reduce to service Lido Core withdrawals | Assigned by DAO under extreme Lido Core liquidity shortage | Rebalancing or burning shares | -| Lido fees | 3 | ETH | Lido protocol service fees | Accrue continuously on each report | Manually permissionlessly, automatically on disconnect | - -#### Bad debt - -The reserve ratio ensures that stETH minted by a vault is overcollateralized. When a vault drops below the force rebalance threshold, it should be rebalanced to restore the collateralization ratio. However, in severe mass-slashing events, vault total value can drop below 1:1 ratio, meaning the vault's total value cannot fully cover outstanding stETH liability. This is bad debt. - -Bad debt is resolved through an escalation path: - -1. **Vault replenishment**: Voluntary deposit of additional funds to cover the debt -2. **Bad debt socialization**: DAO-initiated shifting of uncovered liability to other vaults operated by the same node operator. The accepting vault must have sufficient capacity to absorb the extra liability without breaching its own health threshold. This keeps the operator responsible for all their vaults rather than isolating losses -3. **Self-coverage application**: DAO-initiated coverage application mechanisms, e.g. applying a dedicated reserve fund -4. **Bad debt internalization**: As a last resort, Lido DAO is able to write off the vault's remaining bad debt and accept losses to the protocol by decreasing stETH token rebase. - -### 3.3 LazyOracle - -LazyOracle is a contract that handles accounting reports for Lido vaults. LazyOracle receives a daily snapshot from the AccountingOracle (which reports for the entire Lido protocol). This "lazy oracle" mechanism efficiently handles state updates across potentially thousands of individual vaults. Rather than updating each vault's state in a single transaction—which would be prohibitively expensive in terms of gas costs—the system uses a Merkle tree-based approach where only the root hash representing the global state is stored and updated daily by the AccountingOracle as part of the main accounting protocol report. - -Individual vault updates happen on-demand by providing Merkle proofs verifying a specific vault's data against the stored root. When a vault's data needs updating, anyone can submit the proof along with the vault's latest data. The system verifies this data against the Merkle root and, if valid, updates the vault's state and forwards the relevant information to the StakingVault contract. - -#### Report Freshness - -Each vault operation that relies on the accuracy of the vault's total value is gated by a freshness check. An individual vault report is deemed **fresh** only when its timestamp matches the latest global report checkpoint published by LazyOracle **and** when less than **two days** have elapsed since that checkpoint. If this is not true, the vault is considered stale. With a stale report, the vault owner cannot: - -- withdraw ETH from the vault, -- mint stETH against the vault, -- rebalance the vault, -- deposit to beacon chain, or -- disconnect from the VaultHub. - -Staleness therefore seals the vault in a conservative state until a fresh report is submitted, ensuring that collateral calculations never proceed on outdated data. - -#### Quarantine - -A quarantine is a timelock LazyOracle places on any sudden jump in a vault's reported value that it cannot immediately confirm on-chain. If the reported total value exceeds normal routine EL/CL rewards, the excess is not reflected in the total value straight away. Instead, the excess is pushed into a quarantine buffer and ignored for a predefined period; only after that delay is the quarantined value released into VaultHub's total value. If another jump occurs during the quarantine period, the initial amount is released at the end of the current quarantine, and the cumulative amount of the new excesses enters a new quarantine period starting right after the first one ends. - -This timelock mechanism gives the protocol the time to inspect a sudden growth and raise alarm if necessary. - -Normal top-ups—where the owner funds ether to the vault contract first—never go through quarantine. Because this ether is visible on the vault’s balance, the increase is verifiable on-chain and therefore treated as safe. In practice, this means direct funding is reflected in total value immediately. - -:::warning -Aside from some sanity checks, the quarantine operates in relative terms, so a sudden jump in total value might be quarantined in a small vault but the same amount of growth may not be subject to quarantine in a vault with a large total value. -::: - -**LazyOracle source code:** https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/LazyOracle.sol - -### 3.4 OperatorGrid - -The OperatorGrid contract controls mint parameters of vaults connected to the Lido protocol. Its primary purpose is to organize vaults into groups of tiers with specific stETH minting limits while ensuring no single node operator can service a disproportionate amount of stETH. - -A **group** represents a node operator. Each group has a total shareLimit that caps the total stETH shares that can be minted across all of the operator's vaults. A group contains one or more tiers. Groups track their liability shares (total shares minted by all vaults in the group). - -:::important -The node operator address in OperatorGrid is the same address set as the node operator in the StakingVault contract. This address has critical permissions. Losing access to this address means losing the ability to manage vault configurations and coordinate with vault owners on parameter changes. So it is highly advised that node operators should use multisig accounts. -::: - -A **tier** represents a set of minting parameters. Each tier belongs to a specific node operator group (except the default tier). Each tier has its share limit, reserve ratio, forced rebalance threshold, and Lido fee. Tiers track their liability shares (minted by vaults in that tier). - -OperatorGrid source code: https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/OperatorGrid.sol - -#### Default Tier - -All vaults start in the default tier. The default tier has no specific node operator group. It has its stETH minting limits defined at initialization. Vaults in the default tier don't contribute to any operator group's liability. When a vault moves from the default tier to an operator tier, its shares are added to that operator's group liability. - -A new vault is placed in the default tier even if the vault node operator has a registered group. The vault can change its tier, which must be confirmed by both the vault owner and the node operator. Upon disconnection, the vault drops back to the default tier. - -#### Tier Parameters - -Each tier defines critical parameters that control a vault's stETH minting capacity: - -- **share limit**: the number of stETH shares that can be minted by all vaults in this tier, -- **reserve ratio**: how much ETH must be reserved for each stETH minted, -- **forced rebalance threshold**: a threshold for forced rebalancing, -- **Lido fee**: the fee percentage charged to the Lido treasury. - -These parameters are propagated to VaultHub when a vault connects or changes tier. - -Diagram. An example group with a 100k limit and three tiers -![An example group with 100k limit and 3 tiers](/img/stvaults/tech-design/operatorgrid-group-3-tiers.png) - -#### Tier change flow - -A tier change is performed via a multi-confirmed action (see Dashboard, Multi-confirmation): both the vault owner and the corresponding node operator must independently submit matching tier changes within a set timeframe of each other but regardless of order. Each confirmation is stored on-chain, expires automatically if not completed in time, and can be resubmitted without side effects. Once the second transaction arrives, the contract reallocates the vault’s liability from the old tier to the new one, updates the group and tier share counters, and—if the vault is already connected—pushes the new mint parameters straight to VaultHub. - -#### Lido fees - -The OperatorGrid configures three types of Lido fees (nominated in basis points): **infrastructure fee** (compensates for protocol operational costs), **liquidity fee** (charged for stETH liquidity), and **reservation fee** (covers the on-demand liquidity). Fees are set at the tier level when tiers are created and can be updated by DAO either globally for entire tiers or individually for specific vaults. - -#### Individual vault parameters - -A vault can have individual parameters different from its tier: - -- Share limit: the vault owner and node operator can jointly adjust the vault's share limit independently of the tier's share limit (but not exceeding), -- Lido fees: the DAO can update individual vault fees (infrastructure, liquidity, reservation) to differ from tier rates. - -These parameters can be restored by mutual confirmation from both the owner and the node operator via the sync tier method. - -#### Jail - -OperatorGrid can **jail** a vault as a protective measure. The main purpose of the jailing mechanism is to prevent further minting of a problematic vault. - -- While jailed, a vault **cannot mint** new stETH shares. -- Jailing **does not** affect burning or other administrative operations; -- Jailing can be **set or cleared** by DAO. -- Unjailing restores normal minting subject to the usual tier and group limits. - -**OperatorGrid source code:** https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/OperatorGrid.sol - -### 3.5 VaultFactory - -The VaultFactory contract offers a smooth, one-transaction approach to creating and configuring a StakingVault with Dashboard. Crucially, VaultHub accepts only those vaults deployed by the factory. A vault deployed by any other means is rejected. This ensures that the vault contract code is verified and its storage has not been maliciously tampered with. - -The factory performs the following operations: - -- deploys a StakingVault, -- deploys a Dashboard, -- initializes both contracts with the specified parameters, -- optionally configures initial permissions for Dashboard, -- and, in the owner-initiated flow, connects the vault to VaultHub after funding the connect deposit. - -The factory supports two ways to create a StakingVault: - -1. **Vault owner–initiated flow** creates the vault and dashboard, automatically funds the **1 ETH connect deposit** and connects to VaultHub. The function accepts an optional list of role assignments for the vault owner's subroles. -2. **Node operator–initiated flow** creates the vault and dashboard and optionally assigns operator-managed subroles, but **does not connect** to VaultHub. The vault owner later funds the connect deposit and connects to VaultHub. - -**VaultFactory source code:** https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/VaultFactory.sol - -### 3.6 PredepositGuarantee - -To prevent the [deposit frontrunning exploit](https://medium.com/immunefi/rocketpool-lido-frontrunning-bug-fix-postmortem-e701f26d7971), the StakingVault enforces a predeposit-and-verify mechanism. Node operators cannot directly deposit locked assets backing stETH into the beacon chain. Instead, they must use the `PredepositGuarantee` (PDG) contract, which requires node operators to post a matching guarantee amount. - -Through PDG, node operators make 1 ETH predeposits and lock an equivalent guarantee. At the same time, the PDG (as the vault's depositor) stages 31 ETH per validator on the vault, reserving the activation ETH. To verify the validator, a proof of correct withdrawal credentials using [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) beacon block roots must be provided. A positive proof (the validator WC matches the vault) unlocks the guarantee. Only after verification can the validator be fully activated using the staged funds. A negative proof seizes the node operator guarantee in favor of the vault as compensation. - -:::note -For unlocked ETH not backing any stETH, vault owners can opt for a simplified "PDG shortcut" flow that bypasses the guarantee requirement. This easier method assumes trust between the vault owner and node operator (potentially backed by off-chain agreements). In this flow, PDG can directly prove and activate validators, but any malicious frontrunning would impact only the vault owner. -::: - -_Diagram. Node operator deposit happy path_ -![Node operator deposit happy path](/img/stvaults/tech-design/node-operator-deposit-happy-path.png) - -The complete flow of the stVault’s validator deposit is as follows: - -1. The node operator locks 1 ETH guarantee in the PDG contract. -2. The node operator submits a deposit of 1 ETH from the vault via PDG. At the same time, PDG stages 31 ETH for activation. -3. Once the validator appears on the beacon chain, the node operator proves valid withdrawal credentials via PDG. This unlocks the 1 ETH guarantee. -4. The staged 31 ETH plus optional additional amount is deposited to activate the validator. -5. If a validator’s withdrawal credentials are proven invalid, PDG compensates the vault with 1 ETH taken from the operator's guarantee and releases the staged 31 ETH back into the vault’s available balance. - -_Diagram. Proven validator deposit flow_ -![Deposit flow](/img/stvaults/tech-design/deposit-flow.png) - -:::important -- Node operator guarantee can come from a dedicated guarantor account (which trusts the operator). -- The **1 ETH guarantee** always stays in PDG; **only vault ETH** is ever sent to the beacon deposit contract. -- On connection, VaultHub enforces all predeposits in the vault have sufficient staged balance on the vault. -- StakingVaults support [Pectra's EIP-7251](https://eips.ethereum.org/EIPS/eip-7251), so predeposit + activation flows work for both 32 ETH and multi-ETH (up to 2048) validators. -- Most steps in PDG can be batched, including a fast path that proves, activates, and tops up multiple validators in a single call. -- A node operator can attach their PDG balance during predeposit. -- As soon as a validator predeposit is sent, it appears in the beacon deposit queue. Proof of withdrawal credentials can only be generated once the validator is finalized in consensus state. -::: - -##### Node Operator’s Depositor - -For operational flexibility, a node operator can designate a dedicated _depositor_ address (not to be confused with StakingVault.depositor) authorized to perform deposits (including predeposits and activations) through PDG on behalf of that operator. The depositor role is replaceable at any time by the operator without affecting existing balances or guarantees. If unassigned, the depositor defaults to the operator address. - -It is important to note that VaultHub enforces that every connected vault sets PDG as the **depositor** in the vault, while PDG itself verifies that the caller matches the operator-specified depositor. This separation allows secure validator signing operations while keeping administrative keys offline. - -##### Onchain BLS12-381 signature verification - -The predeposit operation must include a valid BLS12-381 signature to pass on-chain verification using the precompiles introduced in [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537). This is why the transaction must also carry the necessary signature transformation data. Signature verification is essential—it ensures that the predeposit is a legitimate deposit and a validator with the specified pubkey will eventually appear on the consensus layer. This will make it possible to generate the presence proof for the validator and its withdrawal credentials. - -:::note -Proven validator top-ups do not require a valid BLS signature, only predeposits. -::: - -##### Proving unknown validators - -The Lido protocol supports direct deposits to the deposit contract and validator consolidations targeting vault-associated validators. To handle such cases, PDG includes a special method for proving the withdrawal credentials of _side_ or _consolidated_ validators—those that either bypassed the standard predeposit flow or were later merged into a vault's validator set. - -This method allows these validators to be cleared in PDG without going through the predeposit process. However, the balance of such validators is excluded from the vault's `totalValue` until it is acknowledged via the oracle report. - -:::important -Only validators that have been activated on the beacon chain can be proven to PDG. Pending validators are rejected because they are not yet eligible for EIP-7002 withdrawal and cannot be force-exited until they activate. -::: - -_Diagram. Proving unknown validator to PDG_ -![image](/img/stvaults/tech-design/proving-unknown-validator.png) - -**PredepositGuarantee source code**: https://github.com/lidofinance/core/blob/v4.0.0/contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol - -### 3.7 Dashboard - -Dashboard is a utility extension for StakingVault and deals with: - -- Granular role-based access control to the StakingVault operations, -- Management and disbursement of the node operator fee, -- PDG predeposit bypass, -- UX-friendly methods and various token helpers. - -:::note -While technically optional, Dashboard is highly recommended for easier operational management of StakingVaults. Without Dashboard, Lido's web interface and CLI utilities **will not function**. Vault owners who choose to operate without Dashboard should possess strong technical knowledge of the underlying contracts and be prepared to manage their vault through raw transaction calls. For most users, Dashboard provides essential quality-of-life improvements that significantly reduce operational complexity when managing validators and stETH minting operations. -::: - -#### Architecture - -StakingVault is a minimal staking primitive that manages only immediate staking operations and tracks its totalValue and locked ETH. It implements a simple single-owner model. Dashboard is optional and operates on top of VaultHub, i.e., it is recorded as the owner of the vault in VaultHub while the actual vault owner becomes the admin of the `Dashboard` contract. - -_Diagram. Dashboard access control model_ - -![Dashboard access control model](/img/stvaults/tech-design/dashboard-access-control-model.png) - -#### Roles - -With Dashboard, every operation in the StakingVault requires the respective role. For example, funding the StakingVault requires that the sender has the `FUND_ROLE`. All of these roles have their [role admin](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessControl-_setRoleAdmin-bytes32-bytes32-). - -_Diagram. Role-restricted operations_ - -![Role-restricted operations](/img/stvaults/tech-design/role-restricted-operations.png) - -:::important -- The `Dashboard` contract includes functions for batch-granting and batch-revoking roles; -- Some operations (like rebalance) can be pre-funded if ether is attached to the transaction and the sender has `FUND_ROLE`. -::: - -#### Multi-role confirmation - -The multi-role confirmation mechanism restricts some administrative actions, thus preventing unilateral decisions. This means that a member of each of the required roles must send the transaction with the same parameters within a configurable duration (lifetime). - -_Diagram. Example of a multi-role confirmation process_ - -![image](/img/stvaults/tech-design/multi-role-confirmation.png) - -#### Node operator fee - -The StakingVault intentionally does not include any accounting for extraneous fees (e.g., node operator, reward share) to allow for flexibility in different setups. Instead, this logic was implemented in `Dashboard` with room for configuration. Dashboard includes the node-operator manager role, which is granted to an address representing the node operator's interests and can differ from the node operator address set in the vault. - -The fee accounting uses a high-water mark approach and is calculated as follows: - -- Define **growth** as the component of the vault’s total value that is _not_ from explicit funding: - $$ - growth = totalValue - inOutDelta - $$ -- Maintain **settled growth** as the high-water mark for the portion of growth that has either: - - already been charged to the operator (paid out), or - - is explicitly exempt (e.g., unguaranteed/side deposits, consolidations). - -So the fee base is: -$$ -unsettled = \max(growth - settledGrowth, 0) -$$ - -The fee is: -$$ -fee = unsettled * feeRate -$$ - -If unsettled is zero or negative, the settled growth remains the same and no fee accrues. - -##### Fee disbursement - -The fee is disbursed permissionlessly (with an exception for abnormally high fees). The disbursement process: - -1. Reads the latest vault report, -2. Computes `unsettled` growth and the fee, -3. Updates **settled growth** to the current growth (so the same amount won’t be charged again), -4. Pays the fee to the configured recipient from the vault’s available balance. - -On a voluntary disconnect, the fee is disbursed automatically first, then disconnect proceeds. - -##### Abnormally high fee - -To protect against misconfigured/outdated settled growth that would result in excessive payouts, Dashboard enforces an **abnormally high fee threshold**. - -- If the fee exceeds **1% of the vault’s total value**, normal permissionless disbursement is blocked. -- In that case, only the vault owner (`DEFAULT_ADMIN_ROLE`) may execute a separate admin function for disbursement. -- This requires the admin to explicitly verify that settled growth is correct before allowing the payment. - -The 1% threshold is highly conservative: with an APR of ~5% and even a 10% operator fee, the vault would take ~2 years to hit the threshold if fees were never disbursed. - -##### Fee change - -Changing the fee rate requires dual confirmation (admin + node-operator manager) and several safety checks: - -- The latest report must be fresh (so accounting is up to date), -- Any recent exemptions/corrections to settled growth must have been recorded _before_ that report (prevents retroactive charging), -- The vault must not be under quarantine (ensures that reported total value is not reduced and fully reflects any exemptions). - -#### PDG policy - -Dashboard enforces a **PDG policy** configured by the admin: - -- **STRICT** - All validator funding must go through the full predeposit-and-prove flow. -- **ALLOW_PROVE** - Node operator can prove validators that did not come through the standard flow (e.g., side deposits), so they become eligible for future top-ups via PDG. -- **ALLOW_DEPOSIT_AND_PROVE** - Node operator can (a) perform **unguaranteed deposits**—withdrawing ETH from the vault and depositing to the beacon contract directly, bypassing the guarantee/signature checks—and (b) later **prove** those validators to PDG. This shortcut assumes trust between the vault owner and operator. - -##### Unguaranteed deposits - -The Dashboard contract provides a shortcut flow for node operators, allowing them to perform deposits that bypass the standard PDG predeposit process—specifically, skipping the 1 ETH guarantee requirement and BLS signature verification. This path is intended for situations where the vault owner trusts the node operator not to frontrun deposits, or where a formal legal agreement governs the arrangement. - -These _unguaranteed deposits_ are executed by withdrawing ETH from the vault (excluding the locked portion) and making the deposits to the Ethereum deposit contract directly, without routing the transaction through PDG. As a result, the vault's `totalValue` is reduced by the deposit amount, and the protocol assumes no risk associated with the deposit. - -This shortcut flow automatically adjusts the vault's node operator fee accounting by updating the settled growth. The associated validator is excluded from reward calculations, so the node operator only receives rewards actually earned—not a share of the full validator balance. Once the validator becomes active, its withdrawal credentials can be proven using PDG's "unknown validator" proving method. After being proven, the validator can receive top-up deposits through the standard PDG flow. - -_Diagram. PDG shortcut_ -![image](/img/stvaults/tech-design/pdg-shortcut-flow.png) - -Other scenarios—such as validator consolidation or direct deposits made to the deposit contract without passing through the vault—can also result in vault-affiliated validators receiving new stake. To ensure accurate reward attribution in these cases, the node operator can manually add a fee exemption in the Dashboard contract that increases the settled growth. - -**Dashboard source code:** https://github.com/lidofinance/core/blob/master/contracts/0.8.25/vaults/dashboard/Dashboard.sol - -## 4. Flows - -#### Staking and Unstaking - -![Staking and unstaking flow](/img/stvaults/tech-design/staking-unstaking-flow.png) - -1. **Funding** - - - The _vault owner_ calls `fund()` on VaultHub to send ETH to the stVault. - - Increases the vault's `totalValue`. - -2. **Depositing Validators** - - - The _node operator_ sends deposits via _predeposit guarantee_ to create or top up a validator. - - Can be done in batches. - - Uses `0x02` withdrawal credentials pointing to the vault's address. - - Does not change `totalValue`. - - Reverts if `locked > totalValue`. - -3. **Receiving EL and CL validation rewards** - - - Validator fee recipient can be set to the vault address. - - Although the increase in the vault's balance is not reflected in `totalValue` until updated with a report. - -4. **Exiting Validators** - - - The _vault owner_ can call `requestValidatorExits()` to ask for a voluntary exit. - - The _node operator_, _vault owner_, or `VaultHub` (under extreme conditions) can call `triggerValidatorWithdrawal()` to perform [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) "triggerable withdrawal". - - Once exited, the validator's balance is transferred to the vault. - - Partial withdrawals may be requested only when the vault is healthy. - -5. **Withdrawing** - - The _vault owner_ calls `withdraw()` on VaultHub to take out any amount of **unlocked** ETH (i.e., `totalValue - locked`) from the vault's balance. - - Exiting validators or partial withdrawals are necessary to withdraw staked ETH. - -#### Accessing stETH - -1. **Minting** - -![Minting flow](/img/stvaults/tech-design/minting-flow.png) - -- The _vault owner_ calls `mint()` on the `VaultHub` to mint stETH up to the amount coverable by the locked ether (including RR). -- Increases the vault's `liabilityShares`. -- The minting capacity is limited by current `totalValue`, `liabilityShares`, `shareLimit`, and `reserveRatio`. - -:::note -Minting against a stVault is subject to the protocol-wide minting [rate limits](/guides/lido-tokens-integration-guide#staking-rate-limits). -::: - -2. **Burning** - -![Burning flow](/img/stvaults/tech-design/burning-flow.png) - -- The _vault owner_ calls `burn()` on the `VaultHub` to burn stETH on behalf of the vault. -- Decreases the vault's `liabilityShares`. -- The `locked` amount gets reduced with the next proven update. - -3. **Rebalancing** - ![Rebalancing flow](/img/stvaults/tech-design/rebalancing-flow.png) - -- The _vault owner_ calls `rebalance()` on the `VaultHub` to rebalance ETH out of the vault. -- Reduces both `liabilityShares` and `totalValue` simultaneously by taking ETH from the vault, submitting it 1:1 for stETH via Lido Core, and then burning it on behalf of the vault. -- Improves vault health at the cost of reducing its totalValue. -- Requires validators to be exited or partially withdrawn if staked ETH is intended to be used. -- Can be performed by the _vault owner_ or executed permissionlessly if the vault's `forcedRebalanceThreshold` is breached. - -#### Connecting and Disconnecting - -Each staking vault can operate independently as a basic delegated staking setup. However, to enable stETH minting, it must be connected to the Lido VaultHub, a central contract that manages vault registry and controls minting. - -**Connection Process:** - -1. **Fund the vault**: The vault must have at least 1 ETH (connect deposit) on its balance. -2. **Set the depositor:** The depositor in the vault must reference the Predeposit Guarantee contract. -3. **Transfer ownership to VaultHub:** The vault transfers ownership to VaultHub, thus signaling consent to join. This prevents VaultHub from forcefully connecting vaults. -4. **Connect**: call the connect function on VaultHub, which creates the vault record with default minting parameters retrieved from OperatorGrid. - -**Disconnection Process:** - -1. **Burn Outstanding stETH:** The vault owner must fully burn any stETH still backed by the vault. -2. **Settle any outstanding obligations**. The vault owner must fully repay any existing redemptions and repay Lido fees. -3. **Request Disconnection:** The owner calls the disconnect function on VaultHub, flagging the vault for removal. -4. **Report Confirmation:** The disconnection is finalized during the next VaultHub report; the vault is removed from the records and ownership is transferred back. The vault is removed from its tier in OperatorGrid. If it chooses to connect again, it is placed in the default tier. If any of the vault validators are reported as slashed, the disconnection is aborted. - -#### Vault Ossification - -Staking vaults are deployed using a custom BeaconProxy pattern. Disconnecting a vault from the VaultHub does **not** prevent it from receiving future upgrades via the beacon controlled by the Lido DAO. - -To permanently freeze the vault's logic and reject any future upgrades, the vault owner can _ossify_ it—by pinning the current implementation address in the proxy. This ossification can only be performed **after** the vault has been fully disconnected from VaultHub. - -#### Forced rebalancing - -A cornerstone principle of stVaults design is: - -> **stETH solvency** - all existing stETH can be converted into ETH at a **1:1** ratio - -Thus, each vault must remain solvent, preventing any vault-specific losses from spilling over to stETH holders. The mechanism to enforce this is called _forced rebalancing_: - -- Triggered when the vault's _reserve_ for minted stETH falls below its force-rebalance threshold (e.g., due to slashing or prolonged penalties). - -- Comprises two parts: - - 1. **Forced Validator Withdrawals** (permissionless, via [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002)). - 2. **Forced Rebalance** (permissionless rebalancing using available vault unstaked ETH). - -- Once triggered, no further deposits or withdrawals are allowed until the vault's health is restored. - -- Force-rebalancing restores the collateralization ratio up to Reserve Ratio. - -- The maximum rebalancing amount `X` satisfies: - $$ - \frac{(mintedShares - X)}{(totalValue - X)} = 1 - RR - $$ - -## 5. Risks - -Stakers and ecosystem participants are advised to carefully consider these risks and conduct their own research before participating in stVaults. - -### 5.1 Ecosystem risks - -1. Stake concentration: Mitigated through stVault permissionless creation, risk parameters, and limits, balancing for diverse node operator participation. -2. Token insolvency: Addressed via risk parameters to maintain a reasonable reserve margin for minted stETH alongside local and global limits for the maximum mintable stETH through the stVaults. - -### 5.2 Risks for stVaults stakers - -1. Deposit Frontrunning: Mitigated through the PredepositGuarantee module. -2. Forced rebalancing: Managed with deterministic rules, policies, and continuous monitoring. -3. Slashing Risk: While mitigated through careful node operator selection and monitoring, the possibility of intentional misbehavior or technical issues remains. -4. Liquidity Risk: Potential challenges in converting large amounts of stETH to ETH quickly for Lido Core, especially during market stress, would require stETH redemptions through stVaults. -5. Interoperability risks: Integration with other DeFi protocols may introduce additional complexities and potential vulnerabilities. - -### 5.3 Inherited Risks - -1. Ethereum Risks: Issues with the Ethereum network, such as consensus failures or major protocol changes, could impact stVault operations. -2. Lido Infrastructure Risks: - - stETH Market Price: Stakers risk an exchange price of stETH lower than the inherent value due to prolonged withdrawal times that delay validator exits and make arbitrage and risk-free market-making impossible. - - Smart Contract Security: There is an inherent risk that Lido could contain a smart contract vulnerability or bug; to minimize this risk, the Lido protocol codebase remains open-source, reviewed, audited, rolled out on testnets, and covered by extensive tests and a bug bounty program. - - Oracle failures and data manipulation: The oracle may affect the protocol's accounting state by providing malformed data; the risk is mitigated with consensus mechanisms for the oracle committee and smart contract safety nets. - - Correlated in-protocol mass-slashing: In case of mass-slashing events in Lido Core, the bunker mode activates to socialize conversion rate losses among stETH holders. - - Governance risks: The protocol is maintained and upgraded by the LDO tokenholders. The mitigation of governance risks includes a two-phase voting system, a public delegate voting platform, and Dual Governance dynamic time-lock with a veto process. -3. Other risks. Regulatory and other risks can be found in [Public Risk Disclosure](/prd). - -## 6. Useful Links - -- [Hasu's 2nd GOOSE voted-in proposal](https://snapshot.box/#/s:lido-snapshot.eth/proposal/0xeedef9fea3d782f192410768cabaf6974da40ef36e1d22c7f8fff5fd4cfc7a59) -- [EIP-7002 "Triggerable Withdrawals"](https://eips.ethereum.org/EIPS/eip-7002) -- [EIP-7251 "Increase the MAX_EFFECTIVE_BALANCE"](https://eips.ethereum.org/EIPS/eip-7251) -- [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110) -- [LIP-5 "Mitigations for deposit frontrunning vulnerability"](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-5.md) -- [LIP-31 "Expanding stETH liquidity layer with over-collateralized minting"](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-31.md) -- [LIP-32 "Sanity Checks for stVaults"](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-32.md) diff --git a/run-on-lido/stvaults/builders/basic-stvaults/basic-isolated-staking-setup.md b/run-on-lido/stvaults/builders/basic-stvaults/basic-isolated-staking-setup.md index 25c0ef034..a8efacb35 100644 --- a/run-on-lido/stvaults/builders/basic-stvaults/basic-isolated-staking-setup.md +++ b/run-on-lido/stvaults/builders/basic-stvaults/basic-isolated-staking-setup.md @@ -22,7 +22,7 @@ Competitive offering to native staking — users stake with the same Node Operat ## Economy model and calculator -The vault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. +The stVault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. For custom calculations, use this spreadsheet as a calculator: [Lido stVault Economics Model](https://docs.google.com/spreadsheets/d/1QOnqUvXy6PXMstYTpbSHHivDQ7VloYCjGMKlhvN80as/edit?usp=sharing) @@ -147,7 +147,7 @@ Creating an stVault is a permissionless operation, but in this two-step process
by Command-line Interface ```bash - yarn start vo w create-vault create-without-connecting --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 + yarn start vo w create-vault create-without-connecting --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRate 1 ``` Note down the addresses of the created **Vault** and **Dashboard** contracts — these are the key contracts of your newly created stVault.
@@ -196,7 +196,6 @@ This is a permissioned operation. By default, this permission belongs to the Vau - `TierID`: the ID of the tier to which the stVault will be connected. - `RequestedShareLimit`: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier’s stETH limit. [Learn more about shares and stETH / wstETH tokens](/guides/lido-tokens-integration-guide#steth-internals-share-mechanics). - `payableAmount`: the amount of ETH to supply in the same transaction; minimum is **1 ETH**. -- `currentSettledGrowth`: the amount of unaccounted growth accrued on the vault while it was disconnected; 0 for newly created vaults via the create-without-connecting method. Settled growth is the part of the total growth that has already been charged by the node operator or is not subject to fee (exempted), such as unguaranteed or side deposits, and consolidations accrued while the vault was disconnected.
using stVaults Web UI @@ -224,8 +223,9 @@ This is a permissioned operation. By default, this permission belongs to the Vau 1. Open **Etherscan** and navigate to the **Dashboard** contract — find its address on the [Per-setup addresses](../../concepts-and-reference/architecture-overview.md#per-setup-addresses) page. 2. Call `connectAndAcceptTier`: - - fill out the `payableAmount` field with '1' to supply `1 ETH` in the same transaction. - - set the `_currentSettledGrowth` field to '0' for a newly created vault like in this scenario (if the stVault is newly created but had side deposits before connecting, settled growth must be set accordingly before the connection). + - fill out the `payableAmount` field with '1' to supply `1 ETH` in the same transaction; + - set `_tierId` to the tier to connect to — `0` is the Default tier; + - set `_requestedShareLimit` to the stETH share limit you want for the stVault.
@@ -250,7 +250,7 @@ The 1 ETH Connection Deposit becomes part of the stVault Total Value, can be use
by Command-line Interface ```bash - yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 + yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRate 1 ```
diff --git a/run-on-lido/stvaults/builders/basic-stvaults/leveraged-staking-product.md b/run-on-lido/stvaults/builders/basic-stvaults/leveraged-staking-product.md index ae6782d91..6e95fbe7a 100644 --- a/run-on-lido/stvaults/builders/basic-stvaults/leveraged-staking-product.md +++ b/run-on-lido/stvaults/builders/basic-stvaults/leveraged-staking-product.md @@ -23,7 +23,7 @@ Staking rewards through a chosen Node Operator, full utilization of the availabl | User Interface | Custom | Custom | ## Economy model and calculator -The vault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. +The stVault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. For custom calculations, use this spreadsheet as a calculator: [Lido stVault Economics Model](https://docs.google.com/spreadsheets/d/1QOnqUvXy6PXMstYTpbSHHivDQ7VloYCjGMKlhvN80as/edit?usp=sharing) @@ -43,7 +43,7 @@ For custom calculations, use this spreadsheet as a calculator: [Lido stVault Eco ~9×;
- tVault — Total Value: + stVault — Total Value: 894.85 ETH;
@@ -204,7 +204,7 @@ The 1 ETH Connection Deposit becomes part of the stVault Total Value, can be use
by Command-line Interface ```bash - yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 + yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRate 1 ```
diff --git a/run-on-lido/stvaults/builders/basic-stvaults/staking_with_redemptions_through_steth.md b/run-on-lido/stvaults/builders/basic-stvaults/staking_with_redemptions_through_steth.md index 325412480..14574f506 100644 --- a/run-on-lido/stvaults/builders/basic-stvaults/staking_with_redemptions_through_steth.md +++ b/run-on-lido/stvaults/builders/basic-stvaults/staking_with_redemptions_through_steth.md @@ -22,7 +22,7 @@ Staking rewards through a chosen Node Operator, with [quick redemption coverage | User Interface | Custom | Custom | ## Economy model and calculator -The vault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. +The stVault strategy - ETH is deposited to validators and generates staking rewards; stETH is minted on demand by the Vault Owner. For custom calculations, use this spreadsheet as a calculator: [Lido stVault Economics Model](https://docs.google.com/spreadsheets/d/1QOnqUvXy6PXMstYTpbSHHivDQ7VloYCjGMKlhvN80as/edit?usp=sharing) @@ -155,7 +155,7 @@ The 1 ETH Connection Deposit becomes part of the stVault Total Value, can be use
by Command-line Interface ```bash - yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRateBP 1 + yarn start vo w create-vault create --defaultAdmin --nodeOperator --nodeOperatorManager --confirmExpiry --nodeOperatorFeeRate 1 ```
diff --git a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-delegated-staking.md b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-delegated-staking.md index 7cb71161e..ed9be215d 100644 --- a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-delegated-staking.md +++ b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-delegated-staking.md @@ -53,7 +53,7 @@ To start: :::info -The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the vault upon connection to Lido `VaultHub`. +The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the stVault upon connection to Lido `VaultHub`. The newly created staking vault is automatically connected to Lido `VaultHub` and placed into the default tier. Placement into non-default tiers right upon deployment is not supported. @@ -119,7 +119,7 @@ yarn start defi-wrapper contracts factory w create-pool-stv-steth + cast calldata "changeTier(uint256,uint256)" ``` - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000` (no predecessor required). - `salt`: `0x0000000000000000000000000000000000000000000000000000000000000000` (or any unique value if you need to differentiate identical operations). @@ -262,9 +262,9 @@ Use `--wallet-connect` option for all commands or provide private key to CLI `.e 3. Execute change tier, connect the wallet: - Open **Etherscan** and navigate to the **TimelockController** contract — find its address on the [Per-setup addresses](../../concepts-and-reference/architecture-overview.md#per-setup-addresses) page. - Go to the **Contract** tab → **Write Contract**. - - Click **Connect to Web3** and connect the wallet that holds the **executor role**.Click **Connect to Web3** and connect the wallet that holds the **executor role**. + - Click **Connect to Web3** and connect the wallet that holds the **executor role**. 4. Find the `execute` method in the list and fill out the fields with the **same values** used in the `schedule` call: - - `target`: the `OperatorGrid` contract address. + - `target`: the `Dashboard` contract address. - `value`: `0`. - `payload`: the same ABI-encoded call data used in step 1. - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000`. diff --git a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-custom-strategy.md b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-custom-strategy.md index 75fe4d40b..c4213b2a5 100644 --- a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-custom-strategy.md +++ b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-custom-strategy.md @@ -19,7 +19,7 @@ An end-user staking product with a higher risk/yield profile achieved by deposit | stETH minting capability | Yes, to deposit into a custom DeFi strategy and generate additional DeFi yield | ## Building blocks -| Building block | Solution | Implementation | +| Building block | Solution | Implementation | | -- | -- | -- | | Basis | stVault | Out-of-the-box | | Pooling Wrapper | DeFi Wrapper | Out-of-the-box | @@ -54,7 +54,7 @@ Both paths share the same smart-contract development steps (implementing `IStrat 1. Implement the [`IStrategy`](https://github.com/lidofinance/vaults-wrapper/blob/main/src/interfaces/IStrategy.sol) interface -2. Implement the [`IStrategyFactory`](https://github.com/lidofinance/vaults-wrapper/blob/main/src/interfaces/IStrategyFactory.sol) interface. +2. Implement the [`IStrategyFactory`](https://github.com/lidofinance/vaults-wrapper/blob/main/src/interfaces/IStrategyFactory.sol) interface. The `_deployBytes` parameter can be used to pass additional strategy-specific configuration during deployment. If your strategy doesn't need extra config, it can be ignored. 3. Deploy the strategy factory @@ -93,15 +93,19 @@ yarn start defi-wrapper contracts factory w create-pool-custom \ + --allowListManager 0x0000000000000000000000000000000000000000 \ --strategyFactory \ --strategyFactoryDeployBytes ``` Run `yarn start defi-wrapper contracts factory write create-pool-custom -h` for the full description of all available parameters. +:::warning +On a strategy pool `--allowListManager` has to be the zero address. The CLI rejects any other value while `--strategyFactory` is set, since that role decides which strategies may deposit into the pool. +::: + :::info -The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the vault upon connection to Lido `VaultHub`. +The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` required to be locked on the stVault upon connection to Lido `VaultHub`. :::
@@ -124,14 +128,14 @@ The deployer must have at least `1 ETH` available. This is the `CONNECT_DEPOSIT` | `--reserveRatioGapBP` | Reserve ratio gap in basis points (recommended min: 250) | | `--mintingEnabled` | Enable stETH minting (`true` / `false`) | | `--allowList` | Enable deposit allowlist (`true` / `false`) | -| `--allowListManager` | Address managing the allowlist | +| `--allowListManager` | Address managing the allowlist. Must be the zero address on a strategy pool. | | `--strategyFactory` | Your deployed strategy factory address | | `--strategyFactoryDeployBytes` | Optional hex-encoded bytes passed to your factory's `deploy()` |
:::warning -The minimum recommended value for `reserveRatioGapBP` is `250` (2.5%). It is expected to be sufficient to absorb enough of the vault's performance volatility to keep users' positions healthy in most cases. +The minimum recommended value for `reserveRatioGapBP` is `250` (2.5%). It is expected to be sufficient to absorb enough of the stVault's performance volatility to keep users' positions healthy in most cases. ::: @@ -428,9 +432,9 @@ For stVaults with DeFi Wrapper the process of changing tier is a bit different b Thus, changing tier for a pooled vault is a three-step process: -1. Holder of the Timelock's proposer role calls `TimelockController.schedule` to propose the `OperatorGrid.changeTier` call +1. Holder of the Timelock's proposer role calls `TimelockController.schedule` to propose the `Dashboard.changeTier` call 2. After the timelock period, the holder of the Timelock's executor role calls `TimelockController.execute` for the scheduled proposal -3. Within the confirmation time window period (24 hours at the Mainnet minimum), the Node Operator calls `OperatorGrid.changeTier` with the same parameters +3. Within the confirmation time window period (24 hours at the Mainnet minimum), the Node Operator confirms from their side by calling `OperatorGrid.changeTier(vault, tierId, requestedShareLimit)` — the same tier and share limit, but through a different contract and with the stVault as an extra argument Confirming tier change request requires applying fresh report to vault. [Read more about applying reports](../../vault-owners-curators-and-stakers/basic-stvaults/apply-oracle-reports.md) @@ -496,11 +500,11 @@ Use `--wallet-connect` option for all commands or provide private key to CLI `.e 2. Go to the **Contract** tab → **Write Contract**. 3. Click **Connect to Web3** and connect the wallet that holds the **proposer role**. 4. Find the `schedule` method in the list and fill out the fields: - - `target`: the `OperatorGrid` contract address. + - `target`: the `Dashboard` contract address. - `value`: `0` (no ETH is sent with this call). - - `data`: the ABI-encoded call to `changeTier(address vault, uint256 tierId, uint256 requestedShareLimit)`. You can generate this using tools like [ABI Encoder](https://abi.hashex.org/) or cast from Foundry: + - `data`: the ABI-encoded call to `changeTier(uint256 tierId, uint256 requestedShareLimit)`. You can generate this using tools like [ABI Encoder](https://abi.hashex.org/) or cast from Foundry: ```bash - cast calldata "changeTier(address,uint256,uint256)" + cast calldata "changeTier(uint256,uint256)" ``` - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000` (no predecessor required). - `salt`: `0x0000000000000000000000000000000000000000000000000000000000000000` (or any unique value if you need to differentiate identical operations). @@ -548,9 +552,9 @@ Use `--wallet-connect` option for all commands or provide private key to CLI `.e 3. Execute change tier, connect the wallet: - Open **Etherscan** and navigate to the **TimelockController** contract — find its address on the [Per-setup addresses](../../concepts-and-reference/architecture-overview.md#per-setup-addresses) page. - Go to the **Contract** tab → **Write Contract**. - - Click **Connect to Web3** and connect the wallet that holds the **executor role**.Click **Connect to Web3** and connect the wallet that holds the **executor role**. + - Click **Connect to Web3** and connect the wallet that holds the **executor role**. 4. Find the `execute` method in the list and fill out the fields with the **same values** used in the `schedule` call: - - `target`: the `OperatorGrid` contract address. + - `target`: the `Dashboard` contract address. - `value`: `0`. - `payload`: the same ABI-encoded call data used in step 1. - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000`. diff --git a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-earn-eth.md b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-earn-eth.md index 2d6d8babe..03b32d06f 100644 --- a/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-earn-eth.md +++ b/run-on-lido/stvaults/builders/defi-wrapper/multi-user-staking-with-earn-eth.md @@ -157,9 +157,9 @@ For stVaults with DeFi Wrapper the process of changing tier is a bit different b Thus, changing tier for a pooled vault is a three-step process: -1. Holder of the Timelock's proposer role calls `TimelockController.schedule` to propose the `OperatorGrid.changeTier` call +1. Holder of the Timelock's proposer role calls `TimelockController.schedule` to propose the `Dashboard.changeTier` call 2. After the timelock period, the holder of the Timelock's executor role calls `TimelockController.execute` for the scheduled proposal -3. Within the confirmation time window period (24 hours at the Mainnet minimum), the Node Operator calls `OperatorGrid.changeTier` with the same parameters +3. Within the confirmation time window period (24 hours at the Mainnet minimum), the Node Operator confirms from their side by calling `OperatorGrid.changeTier(vault, tierId, requestedShareLimit)` — the same tier and share limit, but through a different contract and with the vault as an extra argument Confirming tier change request requires applying fresh report to vault. [Read more about applying reports](../../vault-owners-curators-and-stakers/basic-stvaults/apply-oracle-reports.md) @@ -225,11 +225,11 @@ Use `--wallet-connect` option for all commands or provide private key to CLI `.e 2. Go to the **Contract** tab → **Write Contract**. 3. Click **Connect to Web3** and connect the wallet that holds the **proposer role**. 4. Find the `schedule` method in the list and fill out the fields: - - `target`: the `OperatorGrid` contract address. + - `target`: the `Dashboard` contract address. - `value`: `0` (no ETH is sent with this call). - - `data`: the ABI-encoded call to `changeTier(address vault, uint256 tierId, uint256 requestedShareLimit)`. You can generate this using tools like [ABI Encoder](https://abi.hashex.org/) or cast from Foundry: + - `data`: the ABI-encoded call to `changeTier(uint256 tierId, uint256 requestedShareLimit)`. You can generate this using tools like [ABI Encoder](https://abi.hashex.org/) or cast from Foundry: ```bash - cast calldata "changeTier(address,uint256,uint256)" + cast calldata "changeTier(uint256,uint256)" ``` - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000` (no predecessor required). - `salt`: `0x0000000000000000000000000000000000000000000000000000000000000000` (or any unique value if you need to differentiate identical operations). @@ -277,9 +277,9 @@ Use `--wallet-connect` option for all commands or provide private key to CLI `.e 3. Execute change tier, connect the wallet: - Open **Etherscan** and navigate to the **TimelockController** contract — find its address on the [Per-setup addresses](../../concepts-and-reference/architecture-overview.md#per-setup-addresses) page. - Go to the **Contract** tab → **Write Contract**. - - Click **Connect to Web3** and connect the wallet that holds the **executor role**.Click **Connect to Web3** and connect the wallet that holds the **executor role**. + - Click **Connect to Web3** and connect the wallet that holds the **executor role**. 4. Find the `execute` method in the list and fill out the fields with the **same values** used in the `schedule` call: - - `target`: the `OperatorGrid` contract address. + - `target`: the `Dashboard` contract address. - `value`: `0`. - `payload`: the same ABI-encoded call data used in step 1. - `predecessor`: `0x0000000000000000000000000000000000000000000000000000000000000000`. diff --git a/run-on-lido/stvaults/builders/index.mdx b/run-on-lido/stvaults/builders/index.mdx index 182bb51fc..ff1de5423 100644 --- a/run-on-lido/stvaults/builders/index.mdx +++ b/run-on-lido/stvaults/builders/index.mdx @@ -37,7 +37,7 @@ export const GUIDES = { title: 'Conservative Multi-User Delegated Staking', link: './defi-wrapper/multi-user-delegated-staking', description: - 'A conservative staking vault for single or multiple stakers, with no stETH minting or additional DeFi yield strategy. DeFi Wrapper enables a multi-user setup, while its Whitelisting capability allows builders to restrict who can deposit into the vault.', + 'A conservative staking vault for single or multiple stakers, with no stETH minting or additional DeFi yield strategy. DeFi Wrapper enables a multi-user setup, while its Whitelisting capability allows builders to restrict who can deposit into the stVault.', buildingBlocks: [ { block: 'Basis', solution: 'stVault', implementation: 'Out-of-the-box' }, { block: 'Pooling Wrapper', solution: 'stVaults DeFi Wrapper', implementation: 'Out-of-the-box' }, @@ -301,7 +301,7 @@ Answer a few questions below to find the guide that fits your product. ### Staking with stVaults -An **stVault** is an isolated, non-custodial staking primitive with its own withdrawal credentials, controlled by the Vault Owner, who picks a Node Operator once at creation — an immutable choice with no access to the vault's principal. +An **stVault** is an isolated, non-custodial staking primitive with its own withdrawal credentials, controlled by the Vault Owner, who picks a Node Operator once at creation — an immutable choice with no access to the stVault's principal. ### Liquidity by stETH @@ -317,7 +317,7 @@ DeFi Wrapper pools support an **on-chain allowlist** restricting depositors, tha ### Connector to EarnETH -The DeFi Wrapper has a built-in connector to **Lido EarnETH**: as ETH is supplied to the vault, stETH is minted automatically and sent into EarnETH, adding extra yield on top of staking rewards — enabled at deployment, no custom integration needed. +The DeFi Wrapper has a built-in connector to **Lido EarnETH**: as ETH is supplied to the stVault, stETH is minted automatically and sent into EarnETH, adding extra yield on top of staking rewards — enabled at deployment, no custom integration needed. ### DeFi Wrapper embeddable widget diff --git a/run-on-lido/stvaults/concepts-and-reference/architecture-overview.md b/run-on-lido/stvaults/concepts-and-reference/architecture-overview.md index 42a67a721..a30b1baf3 100644 --- a/run-on-lido/stvaults/concepts-and-reference/architecture-overview.md +++ b/run-on-lido/stvaults/concepts-and-reference/architecture-overview.md @@ -69,7 +69,7 @@ are deployed per setup. Three ways to look them up: #### Web UI -Connect the wallet at the [stVaults Web UI](#interfaces) and open the vault. Its page lists the StakingVault +Connect the wallet at the [stVaults Web UI](#interfaces) and open the stVault. Its page lists the StakingVault and Dashboard addresses. The DeFi Wrapper widget is deployed per pool, so a depositor gets the pool address from whoever runs the product. @@ -78,9 +78,8 @@ from whoever runs the product. From a vault address to the rest of a basic stVault setup: ```bash -yarn start contracts vault r owner # the Dashboard +yarn start contracts v-v r vault-data # connection data; its `owner` field is the Dashboard yarn start contracts dashboard r vault # back to the StakingVault -yarn start contracts v-v r vault-data # connection parameters; `owner` is the Dashboard ``` For a DeFi Wrapper setup, one call returns the whole set — vault, Dashboard, withdrawal queue, distributor @@ -102,7 +101,7 @@ With any one address in hand, the rest follow from the **Read Contract** tab: | On this contract | Call | To get | | --- | --- | --- | -| StakingVault | `owner` | Dashboard | +| VaultHub | `vaultConnection(vault).owner` | Dashboard | | Dashboard | `stakingVault` | StakingVault | | pool | `VAULT`, `DASHBOARD`, `WITHDRAWAL_QUEUE`, `DISTRIBUTOR`, `VAULT_HUB` | the rest of the setup | | WithdrawalQueue | `POOL`, `VAULT`, `DASHBOARD`, `LAZY_ORACLE` | the rest of the setup | diff --git a/run-on-lido/stvaults/concepts-and-reference/audits.md b/run-on-lido/stvaults/concepts-and-reference/audits.md index 0ca2c819e..74daa08d3 100644 --- a/run-on-lido/stvaults/concepts-and-reference/audits.md +++ b/run-on-lido/stvaults/concepts-and-reference/audits.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 9 --- # stVaults Audits diff --git a/run-on-lido/stvaults/concepts-and-reference/defi-wrapper-technical-design.md b/run-on-lido/stvaults/concepts-and-reference/defi-wrapper-technical-design.md index c001ecf20..4a1a80a27 100644 --- a/run-on-lido/stvaults/concepts-and-reference/defi-wrapper-technical-design.md +++ b/run-on-lido/stvaults/concepts-and-reference/defi-wrapper-technical-design.md @@ -401,7 +401,7 @@ The pause roles go to the emergency committee at deployment; the Dashboard's `PA :::warning **No address holds the resume roles after deployment.** Every implementation constructor pre-pauses its features, and the factory grants only the pause halves. `DEPOSITS_RESUME_ROLE`, `MINTING_RESUME_ROLE`, `WITHDRAWALS_RESUME_ROLE`, `FINALIZE_RESUME_ROLE`, the strategy resume roles and `LOSS_SOCIALIZER_ROLE` are unassigned. -Pausing is therefore fast and unpausing is not: resuming requires a timelock proposal to grant the resume role first, then a second call to use it. Plan that delay into any incident response. +Pausing is therefore fast and unpausing is not: resuming means granting the resume role and then using it, neither of which any address can do on its own. Both calls fit in one `scheduleBatch` operation, so the cost is a single timelock delay rather than two — plan that delay into any incident response. ::: #### Role summary diff --git a/run-on-lido/stvaults/concepts-and-reference/exit-validators-permissions.md b/run-on-lido/stvaults/concepts-and-reference/exit-validators-permissions.md index ddcf611eb..5ed19aa8d 100644 --- a/run-on-lido/stvaults/concepts-and-reference/exit-validators-permissions.md +++ b/run-on-lido/stvaults/concepts-and-reference/exit-validators-permissions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 7 title: Exit Validators Permissions and Principles sidebar_label: Exit Validators Permissions --- diff --git a/run-on-lido/stvaults/concepts-and-reference/how-quarantine-works.md b/run-on-lido/stvaults/concepts-and-reference/how-quarantine-works.md index e649ea8a9..4376adfac 100644 --- a/run-on-lido/stvaults/concepts-and-reference/how-quarantine-works.md +++ b/run-on-lido/stvaults/concepts-and-reference/how-quarantine-works.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 8 --- # How Quarantine Works diff --git a/run-on-lido/stvaults/concepts-and-reference/index.md b/run-on-lido/stvaults/concepts-and-reference/index.md index be2c46cd5..10099dfa5 100644 --- a/run-on-lido/stvaults/concepts-and-reference/index.md +++ b/run-on-lido/stvaults/concepts-and-reference/index.md @@ -10,7 +10,6 @@ sidebar_position: 5 4. [DeFi Wrapper Technical Design and Architecture](./defi-wrapper-technical-design.md) — the detailed design behind the DeFi Wrapper. 5. [stVaults Roles and Permissions](./roles-and-permissions.md) — the two-admin model and delegatable sub-roles behind a Basic stVault's `Dashboard`. 6. [stVaults Metrics](./metrics.md) — every stVault metric and the formula behind it. -7. [RR, Limits, fees, and Tiers principles](./rr-limits-fees-tiers.md) — how Reserve Ratio, minting limits, fees, and tiers relate. -8. [Exit validators permissions and principles](./exit-validators-permissions.md) — who may trigger a Consensus Layer withdrawal, and when. -9. [How Quarantine works](./how-quarantine-works.md) — the timelock LazyOracle applies to unconfirmed Total Value growth. -10. [stVaults Audits](./audits.md) — audit reports for V3 and stVaults. +7. [Exit validators permissions and principles](./exit-validators-permissions.md) — who may trigger a Consensus Layer withdrawal, and when. +8. [How Quarantine works](./how-quarantine-works.md) — the timelock LazyOracle applies to unconfirmed Total Value growth. +9. [stVaults Audits](./audits.md) — audit reports for V3 and stVaults. diff --git a/run-on-lido/stvaults/concepts-and-reference/rr-limits-fees-tiers.md b/run-on-lido/stvaults/concepts-and-reference/rr-limits-fees-tiers.md deleted file mode 100644 index d336b9525..000000000 --- a/run-on-lido/stvaults/concepts-and-reference/rr-limits-fees-tiers.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -sidebar_position: 7 -title: Reserve Ratio, Limits, Fees, and Tiers principles -sidebar_label: Reserve Ratio, Limits, Fees, and Tiers principles ---- - -# Reserve Ratio, Limits, Fees, and Tiers principles - -TBD diff --git a/run-on-lido/stvaults/concepts-and-reference/stvaults-technical-design.md b/run-on-lido/stvaults/concepts-and-reference/stvaults-technical-design.md index 75128e194..722f2ea3a 100644 --- a/run-on-lido/stvaults/concepts-and-reference/stvaults-technical-design.md +++ b/run-on-lido/stvaults/concepts-and-reference/stvaults-technical-design.md @@ -666,8 +666,8 @@ Thus, each vault must remain solvent, preventing any vault-specific losses from - Comprises two parts: - 1. **Forced Validator Withdrawals** (permissionless, via [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002)). - 2. **Forced Rebalance** (permissionless rebalancing using available vault unstaked ETH). + 1. **Forced Validator Withdrawals** — requires `VALIDATOR_EXIT_ROLE` on `VaultHub`, via [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002); see [Exit validators permissions](./exit-validators-permissions.md). + 2. **Forced Rebalance** — permissionless, using available vault unstaked ETH. - Once triggered, no further deposits or withdrawals are allowed until the vault's health is restored. diff --git a/run-on-lido/stvaults/faq.md b/run-on-lido/stvaults/faq.md index b1c506b41..5236611ad 100644 --- a/run-on-lido/stvaults/faq.md +++ b/run-on-lido/stvaults/faq.md @@ -11,10 +11,10 @@ sidebar_position: 6 Yes. You can mint stETH right after supplying ETH to your stVault — you don't need an active validator, or even a validator at all, to mint. -The nuance shows up on the other side: once you've minted, how you deposit that ETH to a validator depends on the deposit method, because minted ETH is locked as collateral and can no longer be withdrawn from the vault. +The nuance shows up on the other side: once you've minted, how you deposit that ETH to a validator depends on the deposit method, because minted ETH is locked as collateral and can no longer be withdrawn from the stVault. - The [**full PDG flow**](./node-operators/basic-stvaults/pdg#full-cycle-trustless-path-through-pdg) deposits directly from the stVault Balance without withdrawing ETH first, so this way stays available even when your minting capacity is fully utilized. -- The [**PDG shortcut**](./node-operators/basic-stvaults/pdg#pdg-shortcut) works by withdrawing ETH from the vault and side-depositing it to the validator — which isn't possible once that ETH is locked as collateral for minted stETH. +- The [**PDG shortcut**](./node-operators/basic-stvaults/pdg#pdg-shortcut) works by withdrawing ETH from the stVault and side-depositing it to the validator — which isn't possible once that ETH is locked as collateral for minted stETH. This also affects whether **Ongoing Deposits** — ETH already sent to a validator but still sitting in the beacon chain activation queue — count toward your minting capacity: diff --git a/run-on-lido/stvaults/node-operators/basic-stvaults/consolidation.md b/run-on-lido/stvaults/node-operators/basic-stvaults/consolidation.md index 06340a998..93af64ab1 100644 --- a/run-on-lido/stvaults/node-operators/basic-stvaults/consolidation.md +++ b/run-on-lido/stvaults/node-operators/basic-stvaults/consolidation.md @@ -20,7 +20,7 @@ The consolidation mechanism only transfers the effective balance from source val ## 1. Setup stVaults CLI tool -Use [these instructions](https://lidofinance.github.io/lido-staking-vault-cli/) to setup stVaults CLI. +Use [these instructions](https://lidofinance.github.io/lido-staking-vault-cli/) to set up the stVaults CLI. ## 2. Preconditions @@ -78,9 +78,9 @@ You can check a validator's credentials or state at [beaconcha.in](https://beaco - A list of source pubkeys of validators that you want to consolidate from. - A list of target pubkeys of validators that you want to consolidate to. -- The [Dashboard](/contracts/dashboard) contract address used to control the stVault. It is the owner of the stVault, so you can read it from the vault: +- The [Dashboard](/contracts/dashboard) contract address used to control the stVault. Read it from the stVault's connection data, where it is the `owner` field: ```bash - yarn start contracts vault r owner + yarn start contracts v-v r vault-data ``` Other ways to find it are on the [Per-setup addresses](../../concepts-and-reference/architecture-overview.md#per-setup-addresses) page. - You need ETH to cover the consolidation fee. The exact amount depends on the number of public keys and the current state of the blockchain. You can determine the fee for a single consolidation request by calling the view function [`getConsolidationRequestFee`](/contracts/validator-consolidation-requests#getconsolidationrequestfee) on the [`ValidatorConsolidationRequests`](/contracts/validator-consolidation-requests) contract. The total amount required will be calculated as the number of consolidations multiplied by the fee per request. diff --git a/run-on-lido/stvaults/node-operators/basic-stvaults/pdg.md b/run-on-lido/stvaults/node-operators/basic-stvaults/pdg.md index c4b1f5370..bf69b7b4c 100644 --- a/run-on-lido/stvaults/node-operators/basic-stvaults/pdg.md +++ b/run-on-lido/stvaults/node-operators/basic-stvaults/pdg.md @@ -68,8 +68,8 @@ Steps: using Command-line Interface ```bash - yarn start deposits write set-no-guarantor - # where is the address that will act as the Guarantor + yarn start deposits write set-no-guarantor + # runs interactively and prompts for the address that will act as the Guarantor ```
@@ -83,8 +83,8 @@ Steps: using Command-line Interface ```bash - yarn start deposits write set-no-depositor - # where is the address that will act as the Depositor + yarn start deposits write set-no-depositor -d + # -d is optional; without it the CLI prompts for the address ```
@@ -192,7 +192,7 @@ Steps: yarn start deposits write prove-and-activate -i # Or prove, activate AND top up in one transaction (combines steps 7 and 9): - yarn start deposits write prove-and-top-up -v + yarn start deposits write prove-and-top-up -v ```
@@ -342,8 +342,8 @@ Steps: using Command-line Interface ```bash - yarn start deposits write set-no-depositor - # where is the address that will act as the Depositor + yarn start deposits write set-no-depositor -d + # -d is optional; without it the CLI prompts for the address ``` @@ -372,7 +372,7 @@ Steps: As a result: - - 6.1. ETH is withdrawn from the stVault's withdrawable balance. + - 6.1. ETH is withdrawn from the stVault's withdrawable balance. This requires a fresh oracle report, since `VaultHub.withdraw` refuses a stale one. - 6.2. stVault Total Value is reduced by the deposit amount until the validator appears in the Beacon Chain state AND is included in a subsequent Oracle report. - 6.3. ETH is deposited to the validator via the Ethereum Deposit Contract. diff --git a/run-on-lido/stvaults/node-operators/basic-stvaults/validators-basics.md b/run-on-lido/stvaults/node-operators/basic-stvaults/validators-basics.md index 87f96db8d..8218513dc 100644 --- a/run-on-lido/stvaults/node-operators/basic-stvaults/validators-basics.md +++ b/run-on-lido/stvaults/node-operators/basic-stvaults/validators-basics.md @@ -76,6 +76,8 @@ yarn start contracts vault write eject-validators \ Public keys are a comma-separated list. The CLI reads the current fee itself and attaches it to the transaction, then asks for confirmation before sending. +`` is required by the CLI but does not reach the contract: it is used to size the fee and to print the confirmation, while the call itself carries only the public keys and the refund recipient. Exits through this route are always full. +
diff --git a/run-on-lido/stvaults/node-operators/defi-wrapper/manage-withdrawal-queue.md b/run-on-lido/stvaults/node-operators/defi-wrapper/manage-withdrawal-queue.md index 3d94feeed..c51f123a6 100644 --- a/run-on-lido/stvaults/node-operators/defi-wrapper/manage-withdrawal-queue.md +++ b/run-on-lido/stvaults/node-operators/defi-wrapper/manage-withdrawal-queue.md @@ -21,7 +21,7 @@ It prints the pool, queue and vault addresses, then the numbers that decide the | Is Report Fresh | whether finalization is possible at all right now | | Requests to Finalize | how many requests are waiting | | Unfinalized ETH | what those requests will pay out in total | -| ETH Available for Finalization | what the vault can cover today | +| ETH Available for Finalization | what the stVault can cover today | | **ETH to Withdraw from CL** | the shortfall — how much has to come back from validators | | Is Finalization Paused | whether the feature has been paused | | Min Withdrawal Delay | how long a request must sit before it can be settled | @@ -62,24 +62,24 @@ yarn start contracts vault r staged-balance ## Bringing ETH back from validators -When the vault cannot cover the queue, ETH has to come back from the Consensus Layer. Three routes, with different owners: +When the stVault cannot cover the queue, ETH has to come back from the Consensus Layer. Three routes, with different owners: ```bash # Ask the Node Operator to exit — emits an event, nothing more -yarn start contracts vault w no-val-exit +yarn start contracts dashboard w exit # Node Operator exits directly, full exits only yarn start contracts vault w eject-validators # Owner-side EIP-7002 withdrawal, full or partial -yarn start contracts vault w trigger-v-w +yarn start contracts dashboard w trigger-validator-withdrawal ``` -The first is a request, not an action: `requestValidatorExit` emits `ValidatorExitRequested` per key and stops there. `eject-validators` is the Node Operator's own instrument — it is checked against the Node Operator address, cannot be delegated, and always performs full exits. +The first is a request, not an action: `requestValidatorExit` emits `ValidatorExitRequested` per key and stops there. `eject-validators` is the Node Operator's own instrument — it is checked against the Node Operator address, cannot be delegated, and always performs full exits. Its `` argument is used only to size the fee and to print a confirmation; the contract call carries public keys and a refund recipient, nothing else. Both on-chain routes pay the EIP-7002 fee per public key. It is set by the network and rises while the withdrawal queue is congested, so read it with `calculateValidatorWithdrawalFee` and send a surplus; the excess is refunded. -An exit request has to clear the Consensus Layer exit queue and then the sweep before the ETH lands on the vault. Those two dominate the timeline; the queue's own minimum delay is the smallest part of a depositor's wait. +An exit request has to clear the Consensus Layer exit queue and then the sweep before the ETH lands on the stVault. Those two dominate the timeline; the queue's own minimum delay is the smallest part of a depositor's wait. See [Validators basics](../basic-stvaults/validators-basics.md) for the full picture of who may do what. @@ -94,7 +94,7 @@ yarn start dw uc wo w finalize-withdrawals | `--max-requests ` | 1000 | upper bound on requests settled in one transaction | | `--gas-coverage-recipient
` | the sender | where the gas cost coverage is paid | -The call walks the queue in order and stops at the first request it cannot settle — it never skips ahead. A run that finalizes fewer requests than expected is normal: the vault ran out of available ETH, the minimum delay has not elapsed, or no oracle report has landed since the request was created. The exact conditions are in [Finalization](../../concepts-and-reference/defi-wrapper-technical-design.md#finalization). +The call walks the queue in order and stops at the first request it cannot settle — it never skips ahead. A run that finalizes fewer requests than expected is normal: the stVault ran out of available ETH, the minimum delay has not elapsed, or no oracle report has landed since the request was created. The exact conditions are in [Finalization](../../concepts-and-reference/defi-wrapper-technical-design.md#finalization). If `finalize` reverts outright, the usual causes are a stale report or a paused finalization feature — both visible in `withdrawal-status`. @@ -108,7 +108,7 @@ It is **0 by default**, so nothing is deducted until it is set. Raising it is a yarn start dw uc wo w set-finalization-gas-cost-coverage ``` -Two consequences follow. Coverage is part of what a finalization has to pay out, so raising it raises the vault balance needed to settle the same set of requests. And a request whose payout is smaller than the coverage surrenders only what it has, never going negative — which is also what makes a non-zero coverage discourage flooding the queue with dust. +Raising coverage changes how a request's payout is split between the depositor and the finalizer; it does not change the vault balance needed to settle that request. The gross amount withdrawn stays the same, because the coverage is subtracted from the claimable amount rather than added to it. A request whose payout is smaller than the coverage surrenders only what it has, never going negative — which is also what makes a non-zero coverage discourage flooding the queue with dust. The ceiling and the checkpoint behaviour are described in [Gas cost coverage](../../concepts-and-reference/defi-wrapper-technical-design.md#gas-cost-coverage). @@ -125,7 +125,8 @@ yarn start dw uc wo w auto-report | `--max-requests ` | **10** | requests per finalization round | | `--polling-interval ` | 300000 (5 min) | how often to check for a new report | | `--callback-url ` | — | POST notification after a report or finalization | -| `--skip-report` / `--skip-finalize` | off | run only one half of the loop | +| `--skip-finalize` | off | submit reports without finalizing | +| `--skip-report` | off | only valid together with `--skip-finalize`; on its own the command refuses to start, because finalization needs a fresh report | | `--gas-coverage-recipient
` | the sender | where coverage is paid | The key holding `FINALIZE_ROLE` has to sign, so this process runs with a hot key. It exits on error and checks for missed reports at startup, which is why the command's own help insists on a process manager for production. diff --git a/run-on-lido/stvaults/node-operators/defi-wrapper/pdg-shortcut-bootstrap-guide.md b/run-on-lido/stvaults/node-operators/defi-wrapper/pdg-shortcut-bootstrap-guide.md index d47e8e255..6bac2d67b 100644 --- a/run-on-lido/stvaults/node-operators/defi-wrapper/pdg-shortcut-bootstrap-guide.md +++ b/run-on-lido/stvaults/node-operators/defi-wrapper/pdg-shortcut-bootstrap-guide.md @@ -1,12 +1,12 @@ --- -sidebar_position: 2 +sidebar_position: 1 --- # PDG Shortcut Bootstrap A freshly deployed pool has no depositors, so it has no ETH to stake and nothing for the operator to run. This guide covers the bootstrap: the operator supplies 32 ETH themselves, activates the first validator with it through the [PDG shortcut](../basic-stvaults/pdg.md#pdg-shortcut), and later recovers that ETH through the ordinary withdrawal queue. -This route keeps the operator out of the vault's custody path: no `WITHDRAW_ROLE`, no direct `Dashboard.fund()`. The ETH goes in as an ordinary pool deposit and comes back as an ordinary withdrawal request, on the same terms as any depositor's. +This route keeps the operator out of the stVault's custody path: no `WITHDRAW_ROLE`, no direct `Dashboard.fund()`. The ETH goes in as an ordinary pool deposit and comes back as an ordinary withdrawal request, on the same terms as any depositor's. Two addresses appear below. **OPERATOR** deposits the ETH and ends up holding the stv. **DEPOSITOR** signs the shortcut transaction. They can be the same address. @@ -42,11 +42,11 @@ On a strategy pool `ALLOW_LIST_MANAGER_ROLE` is not granted to anyone at deploym yarn start dw c stv w deposit-eth 32 0x0000000000000000000000000000000000000000 ``` -Called by OPERATOR. The pool mints stv to OPERATOR and forwards the ETH to the vault; the strategy is not involved even on a strategy pool. Record the amount of stv minted — that is the claim used to get the ETH back in Step 7. +Called by OPERATOR. The pool mints stv to OPERATOR and forwards the ETH to the stVault; the strategy is not involved even on a strategy pool. Record the amount of stv minted — that is the claim used to get the ETH back in Step 7. ## Step 3. Allow the shortcut -The shortcut is refused unless the vault's PDG policy permits it: +The shortcut is refused unless the stVault's PDG policy permits it: ```bash yarn start contracts dashboard w set-pdg-policy 2 @@ -71,10 +71,12 @@ yarn start deposits w unguaranteed-deposit '' -v The argument is an array of deposit structs — `pubkey`, `signature`, `amount` in gwei, `deposit_data_root` — the same data a normal deposit uses. The CLI checks the BLS signature first; `--no-bls-check` skips that. -This withdraws the 32 ETH from the vault and sends it straight to the deposit contract with the vault's withdrawal credentials, bypassing the predeposit. From there the validator takes the ordinary entry path — the deposit is processed, then the validator waits in the activation queue, whose length depends on how many validators are entering at the time. +The stVault's oracle report has to be fresh: the call withdraws from the stVault, and `VaultHub.withdraw` refuses a stale report. Applying one is permissionless — see [Apply oracle reports](../../vault-owners-curators-and-stakers/basic-stvaults/apply-oracle-reports.md). + +This withdraws the 32 ETH from the stVault and sends it straight to the deposit contract with the stVault's withdrawal credentials, bypassing the predeposit. From there the validator takes the ordinary entry path — the deposit is processed, then the validator waits in the activation queue, whose length depends on how many validators are entering at the time. :::warning -The vault's reported Total Value drops by 32 ETH the moment this executes, and the stv price drops with it, because the ETH has left the vault while the validator's balance is not yet reported. Every stv holder sees the dip, not just OPERATOR. On a pool that already has depositors, tell them beforehand. +The stVault's reported Total Value drops by 32 ETH the moment this executes, and the stv price drops with it, because the ETH has left the stVault while the validator's balance is not yet reported. Every stv holder sees the dip, not just OPERATOR. On a pool that already has depositors, tell them beforehand. ::: ## Step 6. Wait for the oracle, then for quarantine @@ -128,5 +130,5 @@ yarn start contracts dashboard w set-pdg-policy 0 ``` :::note -Step 4 is a judgment call rather than a cleanup chore. Leaving the policy at `ALLOW_DEPOSIT_AND_PROVE` keeps the shortcut available for later top-ups, at the cost of leaving a path that moves ETH out of the vault without PDG's guarantee. Setting it back to `STRICT` closes that path; reopening it later is another proposal. +Step 4 is a judgment call rather than a cleanup chore. Leaving the policy at `ALLOW_DEPOSIT_AND_PROVE` keeps the shortcut available for later top-ups, at the cost of leaving a path that moves ETH out of the stVault without PDG's guarantee. Setting it back to `STRICT` closes that path; reopening it later is another proposal. ::: diff --git a/run-on-lido/stvaults/qualified-custodians/index.md b/run-on-lido/stvaults/qualified-custodians/index.md index 530a11c93..fc6fa5cb8 100644 --- a/run-on-lido/stvaults/qualified-custodians/index.md +++ b/run-on-lido/stvaults/qualified-custodians/index.md @@ -50,7 +50,7 @@ Support may vary by jurisdiction, entity, and onboarding scope. Clients should c ## Whitelisting smart contract addresses To use the stVaults infrastructure, the relevant stVaults smart contracts must be whitelisted for interaction. Please ask your administrator or custodian support team to add the required stVaults contract addresses to the whitelist. -Some addresses must be whitelisted before creating your first vault, while vault-specific addresses can only be added after a vault has been created. We recommend whitelisting the core stVaults infrastructure addresses upfront, and adding individual vault contract addresses as new stVaults are deployed. +Some addresses must be whitelisted before creating your first vault, while vault-specific addresses can only be added after an stVault has been created. We recommend whitelisting the core stVaults infrastructure addresses upfront, and adding individual vault contract addresses as new stVaults are deployed. ### stVaults infrastructure addresses to be whitelisted diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/basic-stvaults/index.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/basic-stvaults/index.md index aa3904f9a..39d4cabac 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/basic-stvaults/index.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/basic-stvaults/index.md @@ -8,8 +8,8 @@ sidebar_label: Basic stVaults 1. [Supply/Withdraw ETH, Mint/Repay stETH](./supply-withdraw-mint-repay.md) — the day-to-day operations of any stVault. 2. [Apply Oracle Reports](./apply-oracle-reports.md) — applying the latest LazyOracle report before state-dependent operations. -3. [Rebalance](./rebalance.md) — simultaneous reducing the stVault's Total Value and stETH Liability together, 1:1. -4. [Control Validators and Withdraw ETH from the Beacon Chain](./control-validators.md) — exiting validators, partial withdrawing ETH from validators, and pausing new deposits. +3. [Rebalance](./rebalance.md) — simultaneously reducing the stVault's Total Value and stETH Liability together, 1:1. +4. [Control Validators and Withdraw ETH from the Beacon Chain](./control-validators.md) — exiting validators, partially withdrawing ETH from validators, and pausing new deposits. 5. [Covering Redemptions with stETH Liquidity](./redemptions_coverage_with_steth.md) — minting stETH to pay out redemptions without waiting on the validator exit queue. 6. [Health Monitoring Guide](./health-monitoring-guide.md) — Reserve Ratio, Utilization Ratio, and how to track an stVault's health. 7. [Health Emergency Guide](./health-emergency-guide.md) — what to do when an stVault approaches or breaches its Force Rebalance Threshold. diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/index.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/index.md index 1de46bf22..ce90857ad 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/index.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/index.md @@ -17,5 +17,4 @@ sidebar_label: DeFi Wrapper ## Stakers 1. [Supply and Withdraw](./stakers/supply-withdraw.md) — supplying and withdrawing via the DeFi Wrapper's interfaces. -2. [Rebalance Stakers's Position](./stakers/rebalance.md) — rebalancing a staker's position in the DeFi Wrapper. -3. [Stakers' Emergency Guide](./stakers/emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. +2. [Stakers' Emergency Guide](./stakers/emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/emergency-guide.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/emergency-guide.md index 2efb72c32..0bf5a5693 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/emergency-guide.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/emergency-guide.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 2 --- # Stakers' Emergency Guide @@ -52,13 +52,17 @@ and all of them are permissionless — a depositor can make them without holding **The oracle report may be stale.** Without a fresh one, new requests and deposits are refused. A request also needs a report that landed after it was created: finalization stops at the first request newer than the -latest report. Anyone can apply a report: +latest report. Anyone can apply a report. + +Through the DeFi Wrapper widget this is already handled: every deposit, withdrawal, mint and boost prepends the report to the same transaction +batch, so the two are signed together. If no report is available to apply and the on-chain one has gone stale, the widget refuses to build the +transaction at all rather than let it revert. The command below is for the CLI: ```bash yarn start report w submit -v ``` -**Unassigned liability freezes the whole pool.** While the vault owes more stETH than the pool has on record, +**Unassigned liability freezes the whole pool.** While the stVault owes more stETH than the pool has on record, every movement of stv reverts. Finalization burns the stv behind each request it settles, so the whole call reverts with it, and no new request can be filed either. See [Unassigned liability](../vault-owners-and-curators/metrics.md#unassigned-liability). @@ -67,23 +71,23 @@ Anyone can clear it — neither route has a role check, and both are capped at t differ in who pays: ```bash -# out of the vault's own ETH: lowers Total Value, so every stv holder pays a share +# out of the stVault's own ETH: lowers Total Value, so every stv holder pays a share yarn start dw c stv-steth w rebalance-unassigned-liability # out of the caller's ETH yarn start dw c stv-steth w rebalance-unassigned-liability-with-ether ``` -**An unhealthy vault has nothing to pay out with.** Finalization draws on the vault's withdrawable value, and -a vault below its Forced Rebalance Threshold has none — the whole Total Value is locked as collateral, so a -run stops on its first request. Restoring the vault is permissionless, and it is the one force-rebalance that -unblocks the queue: +**An unhealthy stVault has nothing to pay out with.** Finalization draws on the stVault's withdrawable value, +and an stVault below its Forced Rebalance Threshold has none — the whole Total Value is locked as collateral, +so a run stops on its first request. Restoring the stVault is permissionless, and it is the one +force-rebalance that unblocks the queue: ```bash yarn start contracts hub w v-force-rebalance ``` -See [Rebalance](../../basic-stvaults/rebalance.md) for what this costs the vault. +See [Rebalance](../../basic-stvaults/rebalance.md) for what this costs the stVault. ## Step 3. Ask for what needs a role @@ -113,7 +117,7 @@ governance moves that role to an address that will. Escalate rather than wait. ### Bring ETH back from validators -Finalization pays out of the vault's balance, so a queue that has outrun its ETH stays stuck whoever holds +Finalization pays out of the stVault's balance, so a queue that has outrun its ETH stays stuck whoever holds the role. Validators have to be exited, and the Vault Owner can do that **without the Node Operator** through the Dashboard, which submits an EIP-7002 withdrawal request directly: @@ -122,6 +126,16 @@ yarn start contracts dashboard w trigger-validator-withdrawal \ ``` -This needs `TRIGGER_VALIDATOR_WITHDRAWAL_ROLE` and ETH to cover the protocol's withdrawal fee, which is -dynamic — send a surplus, the excess is refunded to the recipient. See -[Control validators](../../basic-stvaults/control-validators.md). +The call needs ETH for the protocol's withdrawal fee, which is dynamic. The CLI reads the fee and sends exactly that; when calling the contract +directly, send a surplus — the excess is refunded to the recipient. + +There are two ways to get the permission, and they suit different situations: + +**Grant `TRIGGER_VALIDATOR_WITHDRAWAL_ROLE` to an address.** One timelock proposal, after which that address exits validators whenever it needs +to, through the CLI or the Web UI. Worth it when the stVault has many validators or exits will be repeated — the delay is paid once. + +**Call through the Timelock Controller itself.** No grant needed: the timelock holds `DEFAULT_ADMIN_ROLE` on the Dashboard, and the guard is +`onlyRoleMemberOrAdmin`, which admits a role's admin. Every exit is then its own proposal and its own delay, and the scheduled operation has to +carry the fee as its value, so the timelock must hold ETH. + +See [Control validators](../../basic-stvaults/control-validators.md). diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/index.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/index.md index de78a39cd..c5b67f791 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/index.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/index.md @@ -7,5 +7,4 @@ sidebar_label: Stakers # DeFi Wrapper for Stakers 1. [Supply and Withdraw](./supply-withdraw.md) — supplying and withdrawing via the DeFi Wrapper's interfaces. -2. [Rebalance Stakers's Position](./rebalance.md) — rebalancing a staker's position in the DeFi Wrapper. -3. [Stakers' Emergency Guide](./emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. +2. [Stakers' Emergency Guide](./emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/rebalance.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/rebalance.md deleted file mode 100644 index 96e32f7fd..000000000 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/rebalance.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -sidebar_position: 3 -title: Rebalance Stakers's Position -sidebar_label: Rebalance Position ---- - -# Rebalance Stakers's Position \ No newline at end of file diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/supply-withdraw.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/supply-withdraw.md index 194668af3..5653cc2cd 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/supply-withdraw.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/stakers/supply-withdraw.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 1 --- # Supply and Withdraw ETH @@ -8,7 +8,7 @@ How to put ETH into a DeFi Wrapper pool and get it back out, through the Web UI ## What a depositor holds -Depositing ETH into a pool mints **stv**, an ERC-20 claim on the pool's share of the underlying stVault. It is transferable, and it grows in value as the vault earns — nothing is ever distributed to holders, the token just becomes worth more ETH. +Depositing ETH into a pool mints **stv**, an ERC-20 claim on the pool's share of the underlying stVault. It is transferable, and it grows in value as the stVault earns — nothing is ever distributed to holders, the token just becomes worth more ETH. $$ \text{assets} = \text{stv}_{\text{account}} \times \frac{\text{totalAssets}}{\text{totalSupply}} @@ -36,7 +36,7 @@ For a minting pool the form also shows what you would be able to mint against th If the pool has an allowlist, an address that is not on it cannot deposit. -The widget always mints the **maximum** available rather than an amount you pick — neither the deposit form nor the **Mint** button in the vault status takes a number. +The widget always mints the **maximum** available rather than an amount you pick — neither the deposit form nor the **Mint** button in the stVault status takes a number.
@@ -48,15 +48,15 @@ The widget always mints the **maximum** available rather than an amount you pick yarn start dw c stv w deposit-eth # Minting pool: deposit and mint in one call -yarn start dw c stv-steth w deposit-eth-shares -yarn start dw c stv-steth w deposit-eth-wsteth +yarn start dw c stv-steth w deposit-eth-shares [-r ] +yarn start dw c stv-steth w deposit-eth-wsteth [-r ] # Mint or repay later, independently of any deposit yarn start dw c stv-steth w mint-steth-shares yarn start dw c stv-steth w burn-steth-shares ``` -Pass `0` as the referral if there is none. `deposit-eth` accepts `-s, --receiver` to credit the stv to a different address. +The two pools take the referral differently: `deposit-eth` on a plain pool takes it as a positional argument, and passing the zero address (`0x0000000000000000000000000000000000000000`) means none; the minting pool's commands take it as the optional `-r, --referral`, which can simply be left out. `deposit-eth` also accepts `-s, --receiver` to credit the stv to a different address. @@ -100,7 +100,7 @@ The second command fetches the report data and proof and submits them. See [Appl A withdrawal is three stages, and the depositor drives only the first and the last: 1. **You request.** Your stv moves to the Withdrawal Queue and the request records what it is worth. Nothing is paid yet. -2. **The operator finalizes.** Once enough ETH is back on the vault and the delay has passed, the Node Operator settles a batch of requests and locks the ETH for them. +2. **The operator finalizes.** Once enough ETH is back on the stVault and the delay has passed, the Node Operator settles a batch of requests and locks the ETH for them. 3. **The depositor claims.** The locked ETH is transferred to the address named in the call. The wait between stages 1 and 2 is set by how long validators take to exit, not by the pool. The pool's own minimum delay is one hour in every shipped configuration; the Consensus Layer exit queue is what determines the timeline. @@ -171,4 +171,4 @@ Only the holder of `FINALIZE_ROLE` — the Node Operator by default — can fina There is a route that does not depend on that operator, but it runs through the pool's governance rather than through the depositor: `FINALIZE_ROLE` is administered by the Timelock Controller, which can grant it to another address. -**Claiming keeps working regardless.** It is not pausable, and it survives the vault being disconnected from Lido Core. Once ETH is locked against a finalized request, nothing in the system can hold it back. +**Claiming keeps working regardless.** It is not pausable, and it survives the stVault being disconnected from Lido Core. Once ETH is locked against a finalized request, nothing in the system can hold it back. diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/disconnection.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/disconnection.md index 2b350a99d..99c3afaec 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/disconnection.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/disconnection.md @@ -155,7 +155,7 @@ yarn start dw c stv-steth w pause-minting After pausing, any attempts to deposit ETH, mint stETH shares, or mint wstETH will revert. :::warning -Pausing is one-way without governance. The factory hands out only the pause roles, so after deployment no address holds `DEPOSITS_RESUME_ROLE`, `MINTING_RESUME_ROLE` or `WITHDRAWALS_RESUME_ROLE`. Undoing Steps 3.1 and 4 therefore takes two rounds through the Timelock Controller: one to grant the resume role, another to call resume. +Pausing is one-way without governance. The factory hands out only the pause roles, so after deployment no address holds `DEPOSITS_RESUME_ROLE`, `MINTING_RESUME_ROLE` or `WITHDRAWALS_RESUME_ROLE`. Undoing Steps 3.1 and 4 therefore goes through the Timelock Controller: grant the resume role, then call resume. Batch both into one `scheduleBatch` and it costs a single delay. Be sure the disconnect is going ahead before you pause. Abandoning it halfway leaves the pool frozen for its users until governance unfreezes it. ::: @@ -302,10 +302,13 @@ The CLI provides a single command that handles the entire distribution flow: ```bash yarn start dw uc distributor w distribute \ + --skip-transfer \ --mode=snapshot \ --output-path ./distribution.json ``` +`--skip-transfer` is here because Step 7.2 already moved the tokens to the Distributor; without it this call would transfer them a second time. + **Options:** | Option | Description | @@ -318,18 +321,6 @@ yarn start dw uc distributor w distribute | `--skip-set-root` | Generate the tree without setting the root on-chain | | `--skip-write` | Skip writing the distribution JSON to file | -:::info -Since tokens were already transferred to distributor in step 7.2, use `--skip-transfer` to avoid a duplicate transfer: - -```bash -yarn start dw uc distributor w distribute \ - --skip-transfer \ - --mode=snapshot \ - --output-path= -``` - -::: - :::info The caller must have `MANAGER_ROLE` on the Distributor contract. This role is granted upon pool creation to the `--nodeOperatorManager` address. ::: @@ -421,9 +412,11 @@ yarn start dw uc distributor w claim --recipients **Step 3.** Transfer wstETH from the proxy to your wallet: ```bash -yarn start dw c str w safe-transfer-erc20 +yarn start dw c str w safe-transfer-erc20 ``` +The call goes to the **strategy**, not to the proxy. The strategy derives the caller's own proxy from `msg.sender`, so a proxy address is never passed in — which is what stops one user from reaching another's. Each user therefore runs this for themselves. + The `` is in decimal wstETH format (e.g. `1.5`), not raw wei. :::info diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/health-guide.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/health-guide.md index 2af70d50a..e2d0de6a6 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/health-guide.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/health-guide.md @@ -8,7 +8,7 @@ title: 'Health and Rebalance' The key stVault metrics that the Vault Owner should monitor and control are: - **Utilization Ratio** — the share of the stETH minting capacity currently used by the Vault Owner. [Learn more](../../../concepts-and-reference/metrics.md#utilization-ratio) -- **Health Factor** — a metric that reflects the economic state of the vault. It shows how the stETH liability is collateralized by the Total Value. A Health Factor of 100% corresponds to the Forced Rebalance Threshold, meaning that if the Health Factor falls below 100%, the stVault becomes subject to forced rebalancing. [Learn more](../../../concepts-and-reference/metrics.md#health-factor) +- **Health Factor** — a metric that reflects the economic state of the stVault. It shows how the stETH liability is collateralized by the Total Value. A Health Factor of 100% corresponds to the Forced Rebalance Threshold, meaning that if the Health Factor falls below 100%, the stVault becomes subject to forced rebalancing. [Learn more](../../../concepts-and-reference/metrics.md#health-factor) Read more: diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/metrics.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/metrics.md index 21b13552e..fc770b456 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/metrics.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/metrics.md @@ -15,24 +15,27 @@ top: the pool's own accounting, each depositor's position inside it, and the wit | Symbol | Meaning | | --- | --- | | $TV$ | Total Value of the underlying stVault | -| $RR$, $FRT$ | the vault's Reserve Ratio and Forced Rebalance Threshold, as fractions | +| $RR$, $FRT$ | the stVault's Reserve Ratio and Forced Rebalance Threshold, as fractions | | $RR_{p}$, $FRT_{p}$ | the **pool's** own ratios, as fractions | | $A$ | assets an account's stv is worth | | $L_{a}$ | stETH an account has minted, in ETH | | $R_{stv}$ | the stv rate — assets per stv | stv carries **27 decimals** against the asset's 18, so rates involving it are scaled by $10^{36}$ on-chain. -Ratios are stored in basis points (`10000` = 100%). The formulas here use fractions and ETH. +Ratios are stored in basis points (`10000` = 100%). The formulas here use fractions and ETH, while on-chain the minted +amounts and the minting capacity are held in **stETH shares**. Two steps separate the two: shares convert to stETH at +the current share rate, which rises with every rebase, and minted stETH counts as an equal amount of ETH of liability. +Ratios such as the Utilization Ratio are unaffected by the choice, because numerator and denominator convert alike. -$RR_{p}$ and $FRT_{p}$ are the vault's ratios plus a fixed gap, 250 BP in every shipped configuration, which -is what makes the pool force-rebalance an account before the protocol force-rebalances the vault — see +$RR_{p}$ and $FRT_{p}$ are the stVault's ratios plus a fixed gap, 250 BP in every shipped configuration, which +is what makes the pool force-rebalance an account before the protocol force-rebalances the stVault — see [§3.3](../../../concepts-and-reference/defi-wrapper-technical-design.md#33-stvstethpool). ## Pool state metrics ### Total nominal assets -The vault's Total Value minus the fees it owes. This is the raw number the pool prices stv from, before the +The stVault's Total Value minus the fees it owes. This is the raw number the pool prices stv from, before the corrections in [Total assets](#total-assets): $$ @@ -71,13 +74,13 @@ conversions exact. ### Total liability shares -The stETH shares the vault owes Lido Core. The pool separately tracks what its own accounts owe **it**, and -normally the two match. When they do not, the gap has a name: **unassigned liability** if the vault owes +The stETH shares the stVault owes Lido Core. The pool separately tracks what its own accounts owe **it**, and +normally the two match. When they do not, the gap has a name: **unassigned liability** if the stVault owes more, **exceeding minted stETH** if the pool's records do. ### Unassigned liability -The excess of what the vault owes over what the pool has on record — debt no account is registered as owing. +The excess of what the stVault owes over what the pool has on record — debt no account is registered as owing. It arises through bad debt socialization, when the DAO moves uncovered liability onto this vault. $$ @@ -93,8 +96,8 @@ vault's own assets or with ETH they supply — see ### Exceeding minted stETH -The same difference the other way round: the pool has more debt on record than the vault owes, which happens -when the vault's liability is repaid without the pool being involved. +The same difference the other way round: the pool has more debt on record than the stVault owes, which happens +when the stVault's liability is repaid without the pool being involved. $$ \text{exceedingMintedShares} = \max(0,\; \text{totalMintedStethShares} - \text{totalLiabilityShares}) @@ -121,8 +124,7 @@ $$ \text{lock}(L_{a}) = \left\lceil \frac{L_{a}}{1 - RR_{p}} \right\rceil $$ -The account can move any stv above this amount. A transfer that would take the balance below it fails, and -that check runs on every transfer. +The account can move any stv above this amount; a transfer that would take the balance below it fails. ### Threshold assets @@ -146,8 +148,8 @@ $$ \end{aligned} $$ -Both are denominated in stETH shares. The remaining capacity can also be evaluated against ETH not yet -deposited, so a depositor can see what a deposit would let them mint. +The remaining capacity can also be evaluated against ETH not yet deposited, so a depositor can see what a +deposit would let them mint. Rounding always runs against the account — capacity floors, `lock` ceils — so it can never leave a position short of collateral. @@ -168,10 +170,10 @@ $$ HF_{a} = \frac{A \times (1 - FRT_{p})}{L_{a}} \times 100\% $$ -The account is healthy while `HF ≥ 100%`. This is the per-account analogue of the vault's +The account is healthy while `HF ≥ 100%`. This is the per-account analogue of the stVault's [Health Factor](../../../concepts-and-reference/metrics.md#health-factor), measured on one account's own -assets and debt. The vault's figure is an aggregate and says nothing about any single account: one account -can be in breach while the vault as a whole is healthy. +assets and debt. The stVault's figure is an aggregate and says nothing about any single account: one account +can be in breach while the stVault as a whole is healthy. ### Force-rebalance amount @@ -179,11 +181,12 @@ The stETH shares a force-rebalance would repay out of a breached account's own s exactly on the pool reserve ratio: $$ -x = \frac{L_{a} - (1 - RR_{p}) \times A_{\text{shares}}}{RR_{p}} +x = \frac{L_{a}^{\text{shares}} - (1 - RR_{p}) \times A^{\text{shares}}}{RR_{p}} $$ -where $A_{\text{shares}}$ is the account's assets expressed in stETH shares. The derivation, and what happens -when the account's stv does not cover its debt, are in +Both sides are in stETH shares here, because that is how the contract solves it — $A^{\text{shares}}$ is the +account's assets converted at the current share rate. The derivation, and what happens when the account's stv +does not cover its debt, are in [§3.3](../../../concepts-and-reference/defi-wrapper-technical-design.md#33-stvstethpool). ## Withdrawal queue metrics @@ -208,7 +211,7 @@ $$ \text{freeToStake} = \max\bigl(0,\; \text{availableBalance} - \text{unfinalizedAssets}\bigr) $$ -Here $\text{availableBalance}$ is the vault's own balance less the ETH already staged for pending validator +Here $\text{availableBalance}$ is the stVault's own balance less the ETH already staged for pending validator activations. At zero, everything sitting on the balance is spoken for by the queue. ### Rate discount @@ -247,20 +250,20 @@ The pool publishes no APR of its own. Performance is a property of the underlyin gross staking rewards, Node Operator and Lido fees, Gross and Net staking APR, Carry Spread — describe a pool's returns too. -The DeFi Wrapper widget shows depositors an APY derived from those. It reads the vault's **Net staking APR** +The DeFi Wrapper widget shows depositors an APY derived from those. It reads the stVault's **Net staking APR** as a simple moving average from the stVaults API and compounds it daily: $$ \text{staking APY} = \left(1 + \frac{\text{Net staking APR}}{365}\right)^{365} - 1 $$ -The period is a day because an oracle report updates the vault's value once a day, so each day's rewards +The period is a day because an oracle report updates the stVault's value once a day, so each day's rewards start earning from the next one. The compounding is why the APY comes out slightly above the APR it is derived from. ### Strategy pools -A strategy pool earns twice: the vault stakes the ETH, and the stETH minted against it works in the external +A strategy pool earns twice: the stVault stakes the ETH, and the stETH minted against it works in the external protocol. Only the spread over stETH counts — the position is funded with minted stETH, whose rebase the depositor @@ -268,15 +271,17 @@ still owes — and only on the share of the assets actually minted against: $$ \begin{aligned} +U &= \frac{L_{a}}{A} = \frac{UR_{a}}{100\%} \times (1 - RR_{p}) \\[2pt] \text{strategy APR} &= U \times (\text{strategy APR}_{\text{external}} - \text{stETH APR}) \\[2pt] \text{net APR} &= \text{strategy APR} + \text{Net staking APR} \\[2pt] \text{net APY} &= \left(1 + \frac{\text{net APR}}{365}\right)^{365} - 1 \end{aligned} $$ -$U$ is how much of the assets is minted against. The estimate shown before depositing assumes the maximum, -$1 - RR_{p}$; for an existing position the account's own -[Utilization Ratio](#account-utilization-ratio) is used instead. +$U$ is the account's stETH debt divided by its assets, with both amounts expressed in ETH. +$UR_a$ is the account's [Utilization Ratio](#account-utilization-ratio), expressed as a percentage. +Before a deposit, the estimate assumes full use of the minting capacity: $UR_a = 100\%$, so $U = 1 - RR_p$. +For an existing position, use the account's actual Utilization Ratio in the formula for $U$. :::note The strategy term is negative whenever the external protocol yields less than stETH, putting the total below diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/non-custodial-operations.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/non-custodial-operations.md index f0317c960..523976b04 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/non-custodial-operations.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/non-custodial-operations.md @@ -10,7 +10,7 @@ This guide explains how to configure role delegation for an stVault that sits be ## Why this setup matters -An stVault + DeFi Wrapper setup typically needs frequent, low-friction operational actions — adjusting Predeposit Guarantee (PDG) policy, requesting validator exits, pausing deposits, and similar day-to-day tasks. At the same time, the same vault holds staker principal, and a single compromised or malicious operational key should never be able to withdraw funds, mint stETH fron the stVault, or reassign roles. + An stVault + DeFi Wrapper setup typically needs frequent, low-friction operational actions — requesting validator exits, pausing deposits, and similar day-to-day tasks — alongside occasional governance actions such as adjusting Predeposit Guarantee (PDG) policy. At the same time, the same vault holds stakers principal, and a single compromised or malicious operational key should never be able to withdraw funds, mint stETH from the stVault, or reassign roles. The setup below splits stVault permissions into two categories, based on whether an operation can move or re-collateralize staker funds: @@ -20,7 +20,7 @@ The setup below splits stVault permissions into two categories, based on whether ## Prerequisites - The stVault and its DeFi Wrapper are already deployed and connected to VaultHub. -- The operations manager has set up a dedicated multisig (recommended: 2-of-3) that will act as the day-to-day operator of the vault. +- The operations manager has set up a dedicated multisig (recommended: 2-of-3) that will act as the day-to-day operator of the stVault. - A second, broader multisig group is available to act as **Executor** — this should include parties independent from the operations manager, such as a custodian, an auditor, or another trusted counterparty (e.g. a traffic or distribution partner, a builder). :::note diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/roles-and-permissions.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/roles-and-permissions.md index 18a9fa4e5..32cf85c68 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/roles-and-permissions.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/defi-wrapper/vault-owners-and-curators/roles-and-permissions.md @@ -51,7 +51,7 @@ The Pool is an ERC20 share token contract (`StvPool` / `StvStETHPool`) where use - For strategy pools the Strategy contract is added to the allowlist during deployment, and **users are expected to supply via the Strategy** (not via the Pool directly). :::warning -Every role marked **nobody** on this page is unassigned at deployment. Each implementation starts with its features paused and the factory hands out only the pause halves, so resuming takes two timelock rounds: one to grant the resume role, another to use it. Pausing is immediate; unpausing is not. +Every role marked **nobody** on this page is unassigned at deployment. Each implementation starts with its features paused and the factory hands out only the pause halves, so resuming takes two calls: one to grant the resume role, another to use it. Both fit in a single `scheduleBatch` operation on the Timelock Controller, so it is one delay rather than two — but pausing is immediate, and resuming always waits out that delay. ::: ## Withdrawal Queue roles diff --git a/run-on-lido/stvaults/vault-owners-curators-and-stakers/index.md b/run-on-lido/stvaults/vault-owners-curators-and-stakers/index.md index 1ab97cd1b..b77a9496a 100644 --- a/run-on-lido/stvaults/vault-owners-curators-and-stakers/index.md +++ b/run-on-lido/stvaults/vault-owners-curators-and-stakers/index.md @@ -29,5 +29,4 @@ sidebar_position: 3 ### Stakers 1. [Supply and Withdraw](./defi-wrapper/stakers/supply-withdraw.md) — supplying and withdrawing via the DeFi Wrapper's interfaces. -2. [Rebalance Stakers's Position](./defi-wrapper/stakers/rebalance.md) — rebalancing a staker's position in the DeFi Wrapper. -3. [Stakers' Emergency Guide](./defi-wrapper/stakers/emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. \ No newline at end of file +2. [Stakers' Emergency Guide](./defi-wrapper/stakers/emergency-guide.md) — withdrawing ETH from a non-responsive stVault with DeFi Wrapper. \ No newline at end of file diff --git a/static/img/stvaults/builders/architecture_basic.jpg b/static/img/stvaults/builders/architecture_basic.jpg index cb1302cb6..0cd3dbb7a 100644 Binary files a/static/img/stvaults/builders/architecture_basic.jpg and b/static/img/stvaults/builders/architecture_basic.jpg differ diff --git a/static/img/stvaults/builders/architecture_lsp.jpg b/static/img/stvaults/builders/architecture_lsp.jpg index d001d2b70..59e0fd4bb 100644 Binary files a/static/img/stvaults/builders/architecture_lsp.jpg and b/static/img/stvaults/builders/architecture_lsp.jpg differ diff --git a/static/img/stvaults/builders/architecture_public_custom.jpg b/static/img/stvaults/builders/architecture_public_custom.jpg index da3361a32..16d2e8447 100644 Binary files a/static/img/stvaults/builders/architecture_public_custom.jpg and b/static/img/stvaults/builders/architecture_public_custom.jpg differ diff --git a/static/img/stvaults/builders/architecture_public_vault.jpg b/static/img/stvaults/builders/architecture_public_vault.jpg index d2afc221e..e2fddf981 100644 Binary files a/static/img/stvaults/builders/architecture_public_vault.jpg and b/static/img/stvaults/builders/architecture_public_vault.jpg differ diff --git a/static/img/stvaults/builders/architecture_public_vault_earneth.jpg b/static/img/stvaults/builders/architecture_public_vault_earneth.jpg index bac9202df..9d7853104 100644 Binary files a/static/img/stvaults/builders/architecture_public_vault_earneth.jpg and b/static/img/stvaults/builders/architecture_public_vault_earneth.jpg differ diff --git a/static/img/stvaults/builders/architecture_rsp.jpg b/static/img/stvaults/builders/architecture_rsp.jpg index b681836cb..530bd4962 100644 Binary files a/static/img/stvaults/builders/architecture_rsp.jpg and b/static/img/stvaults/builders/architecture_rsp.jpg differ diff --git a/static/img/stvaults/builders/building_blocks.jpg b/static/img/stvaults/builders/building_blocks.jpg index 0e807fbae..8368e4013 100644 Binary files a/static/img/stvaults/builders/building_blocks.jpg and b/static/img/stvaults/builders/building_blocks.jpg differ diff --git a/static/img/stvaults/redemptions.jpg b/static/img/stvaults/redemptions.jpg index 30d2be9d8..0bfa9791c 100644 Binary files a/static/img/stvaults/redemptions.jpg and b/static/img/stvaults/redemptions.jpg differ diff --git a/static/img/stvaults/tech-design/architecture_stv.jpg b/static/img/stvaults/tech-design/architecture_stv.jpg index f1e5ea07b..233303a73 100644 Binary files a/static/img/stvaults/tech-design/architecture_stv.jpg and b/static/img/stvaults/tech-design/architecture_stv.jpg differ diff --git a/static/img/stvaults/tech-design/architecture_stv_wrapper.jpg b/static/img/stvaults/tech-design/architecture_stv_wrapper.jpg index 64feef28d..f2e8c6a18 100644 Binary files a/static/img/stvaults/tech-design/architecture_stv_wrapper.jpg and b/static/img/stvaults/tech-design/architecture_stv_wrapper.jpg differ diff --git a/static/img/stvaults/tech-design/architecture_wrapper.jpg b/static/img/stvaults/tech-design/architecture_wrapper.jpg index a24200c71..b2b299321 100644 Binary files a/static/img/stvaults/tech-design/architecture_wrapper.jpg and b/static/img/stvaults/tech-design/architecture_wrapper.jpg differ