Skip to main content

Staking Flow

Read this page before you call the API methods. It explains how a Lido stVault position works and which steps each action does.

A Lido stVault is a staking vault of Lido V3. You stake ETH into a pool, and the pool funds the staking vault. You can also mint wstETH against the staked ETH and deposit that wstETH into a Mellow vault. A position therefore has two layers:

LayerTokenDecimalsDescription
STV poolSTV27The ETH that you stake. The stake action mints STV. The ETH value of the STV changes with the rewards of the vault.
Mellow vaultMellow vault shares18Optional. The wstETH that you mint against the STV and deposit into the Mellow vault.

The strategy contract creates one call forwarder contract for each address. The call forwarder holds the STV, the Mellow vault shares and the liability of that address. A block explorer shows the position on the call forwarder, not on your address. The position endpoint returns its address as call_forwarder.

More information is available in the official Lido documentation: https://docs.lido.fi/run-on-lido/stvaults/

Minting wstETH is leverage

mint_wsteth_amount borrows against the staked ETH. It is not a plain deposit.

  • The pool reserve ratio limits the amount that you can mint.
  • The minted amount becomes a liability in stETH shares. The position endpoint reports it as minted_steth_shares.
  • If the position goes below the forced rebalance threshold of the pool, any account can rebalance it. The pool then burns STV of the position to repay the liability.

The default value of mint_wsteth_amount is 0. With the default value, the stake action stakes ETH only and the position has no liability.

Staking user journey​

A position that stakes ETH only uses the STV layer:

A position that also mints wstETH adds the Mellow layer on top of the STV position:

The claim, withdraw and claim-pool-withdrawal actions are possible only after the related queue settles the request.

Staking parameters​

Key parameters for planning a Lido stVault integration:

ParameterValue
Staking typeLido V3 staking vault (pooled), with an optional Mellow vault strategy
NetworksHoodi
API minimumNone for stake. One pool withdrawal request must have an ETH value from 0.001 ETH to 10,000 ETH
Stake activationImmediate. The pool mints STV in the stake transaction
Mellow depositAsynchronous. The deposit queue settles the request, then you send claim. No fixed time
Exit from the Mellow vaultunstake, then withdraw after the redeem queue settles the request. No fixed time. You cannot cancel the request
Exit from the STV poolwithdraw-pool, then claim-pool-withdrawal after the queue finalizes the request. The queue has a minimum delay (1 hour on Hoodi) and no fixed maximum time
Rewards modelRewards accrue in the ETH value of the STV. There is no claim action for rewards
Real-time staking data

This table is a summary. For the current fees, APY and stake limits, query the dedicated staking-info endpoint: GET /api/v1/ethereum/lido-stvault/staking-info.


Stake​

The stake action stakes ETH into the STV pool.

  1. Stake ETH: Use the stake method with the amount of ETH. The transaction sends the ETH as its value.
  2. Transaction confirmation: When the transaction is confirmed, the pool mints STV to your call forwarder. The stake is active.
  3. Reward accrual: Rewards change the ETH value of the STV. Read it as stv_assets in the position endpoint.

If you set mint_wsteth_amount, the same transaction also mints that amount of wstETH against the position and deposits it into the Mellow deposit queue. This part does not settle in the stake transaction. See Claim.

Claim​

The claim action is necessary only after a stake with mint_wsteth_amount greater than 0.

  1. Wait for the deposit queue: The Mellow deposit queue settles the deposit request asynchronously. The protocol publishes no fixed time.
  2. Check the position: Read pending_deposit_is_claimable in the position endpoint.
  3. Claim: When the value is true, use the claim method. The Mellow vault shares then become active_shares.

A position can have one deposit request at a time. While a deposit request is pending and not claimable, the strategy rejects a new stake that mints wstETH.

Unstake​

The unstake action starts the exit from the Mellow vault. It does not exit the STV position.

  1. Request the exit: Use the unstake method with the number of Mellow vault shares to redeem.
  2. Redeem queue: The request enters the Mellow redeem queue. You cannot cancel it. The position endpoint lists it in exit_requests.
  3. Ready for withdrawal: When the queue settles the request, is_claimable becomes true and assets shows the wstETH that the request releases.

Withdraw​

The withdraw action finalizes one exit request from the Mellow vault.

  1. Take the identifier: Read request_id of the exit request in the position endpoint.
  2. Withdraw: When is_claimable is true, use the withdraw method with that request_id.
  3. Result: The redeem queue releases the wstETH to your call forwarder. The position endpoint reports it as wsteth. The wstETH does not go to your wallet, and the liability of the position does not change.

Burn wstETH​

The burn-wsteth action repays the liability of the position with the wstETH that the call forwarder holds.

  1. Check the position: Read wsteth and minted_steth_shares in the position endpoint.
  2. Burn: Use the burn-wsteth method with the amount of wstETH to burn. The amount cannot be more than wsteth or more than the liability.
  3. Result: The liability decreases. The STV that covered it can then leave the position through withdraw-pool.

Withdraw from the pool​

The withdraw-pool action starts the exit of the STV position back to ETH.

  1. Request the withdrawal: Use the withdraw-pool method with the stv_amount to withdraw. The transaction moves the STV to the pool withdrawal queue and creates a request that recipient owns.
  2. Liability: If the position has a liability, the STV that stays in the position must still cover it. If it does not, repay the liability first with burn-wsteth, or set steth_shares_to_rebalance. The queue then uses part of the withdrawn STV to repay that amount of stETH shares.
  3. Finalization: An account with the finalizer role of the queue finalizes the requests in order. You do not send this transaction. A request can be finalized only after the minimum delay, after a new oracle report of the vault, and when the vault has enough available ETH.
  4. Claim: The position endpoint of the owner lists the request in pool_withdrawal_requests. When is_claimable is true, use the claim-pool-withdrawal method with its request_id. The owner of the request must sign this transaction. The ETH then goes to the wallet of the owner, or to the recipient of the claim.

Refresh the vault report​

The refresh-report action applies the latest Lido oracle report to the vault.

Lido V3 uses a lazy oracle. Each time Lido publishes a new report, the report of the vault is stale until a transaction applies it. While it is stale, the pool refuses stake and withdraw-pool, and the API returns 422 with the reason VaultReportStale.

  1. Craft the refresh: Use the refresh-report method. Any address can sign and pay for it. The address does not need a position.
  2. Wait for the transaction: Broadcast it and wait until it is mined.
  3. Try again: Craft the refused action again.

Steps that the API does not craft​

The Staking API crafts eight actions: stake, claim, unstake, withdraw, burn-wsteth, withdraw-pool, claim-pool-withdrawal and refresh-report. With these actions you can do a full exit to ETH: unstake, withdraw, burn-wsteth, withdraw-pool, then claim-pool-withdrawal.

One protocol step is not available as an API action. To do it, send the transaction to the contract directly.

StepContractFunction
Move a token out of the call forwarderStrategysafeTransferERC20(address _token, address _recipient, uint256 _amount)

Contracts​

The Lido stVault deployment on Hoodi uses these contracts. The source code of each contract is verified on the block explorer.

ContractAddress on Hoodi
Strategy0xbF4797De82787A60101e5e45CEc7f29b27d83D98
STV pool0xC6B9509E24F9aE488eDd3dCD488559f85678C552
Pool withdrawal queue0xdded18c85c10B96b4B6eB2Ba70016F510bE4C902

Before you sign, make sure that payload.to is the expected contract:

Actionpayload.to
stake, claim, unstake, withdraw, burn-wsteth, withdraw-poolStrategy
claim-pool-withdrawalPool withdrawal queue
refresh-reportLido lazy oracle. The API reads its address from the Lido locator contract

Conditions that block an action​

The contracts refuse an action in some on-chain states. The API simulates each transaction before it returns it. If the simulation fails, the API returns 422 with the reason and does not return a transaction.

  • Stale oracle report: The STV pool needs a fresh oracle report of the vault for stake and withdraw-pool. When the report is stale, the API returns the reason VaultReportStale. Send the refresh-report action, then try again. See Refresh the vault report.
  • Paused feature: The operators of the protocol can pause deposits, minting, redeems and withdrawals.
  • Insufficient balance: The API returns 400 with the requested amount and the available amount.

The full list is in Endpoints, Errors.

API interaction​

All eight actions use the same four steps.