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:
| Layer | Token | Decimals | Description |
|---|---|---|---|
| STV pool | STV | 27 | The ETH that you stake. The stake action mints STV. The ETH value of the STV changes with the rewards of the vault. |
| Mellow vault | Mellow vault shares | 18 | Optional. 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/
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:
| Parameter | Value |
|---|---|
| Staking type | Lido V3 staking vault (pooled), with an optional Mellow vault strategy |
| Networks | Hoodi |
| API minimum | None for stake. One pool withdrawal request must have an ETH value from 0.001 ETH to 10,000 ETH |
| Stake activation | Immediate. The pool mints STV in the stake transaction |
| Mellow deposit | Asynchronous. The deposit queue settles the request, then you send claim. No fixed time |
| Exit from the Mellow vault | unstake, then withdraw after the redeem queue settles the request. No fixed time. You cannot cancel the request |
| Exit from the STV pool | withdraw-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 model | Rewards accrue in the ETH value of the STV. There is no claim action for rewards |
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.
- Stake ETH: Use the
stakemethod with theamountof ETH. The transaction sends the ETH as its value. - Transaction confirmation: When the transaction is confirmed, the pool mints STV to your call forwarder. The stake is active.
- Reward accrual: Rewards change the ETH value of the STV. Read it as
stv_assetsin 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.
- Wait for the deposit queue: The Mellow deposit queue settles the deposit request asynchronously. The protocol publishes no fixed time.
- Check the position: Read
pending_deposit_is_claimablein the position endpoint. - Claim: When the value is
true, use theclaimmethod. The Mellow vault shares then becomeactive_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.
- Request the exit: Use the
unstakemethod with the number of Mellow vaultsharesto redeem. - Redeem queue: The request enters the Mellow redeem queue. You cannot cancel it. The position endpoint lists it in
exit_requests. - Ready for withdrawal: When the queue settles the request,
is_claimablebecomestrueandassetsshows the wstETH that the request releases.
Withdraw
The withdraw action finalizes one exit request from the Mellow vault.
- Take the identifier: Read
request_idof the exit request in the position endpoint. - Withdraw: When
is_claimableistrue, use thewithdrawmethod with thatrequest_id. - 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.
- Check the position: Read
wstethandminted_steth_sharesin the position endpoint. - Burn: Use the
burn-wstethmethod with theamountof wstETH to burn. The amount cannot be more thanwstethor more than the liability. - 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.
- Request the withdrawal: Use the
withdraw-poolmethod with thestv_amountto withdraw. The transaction moves the STV to the pool withdrawal queue and creates a request thatrecipientowns. - 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 setsteth_shares_to_rebalance. The queue then uses part of the withdrawn STV to repay that amount of stETH shares. - 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.
- Claim: The position endpoint of the owner lists the request in
pool_withdrawal_requests. Whenis_claimableistrue, use theclaim-pool-withdrawalmethod with itsrequest_id. The owner of the request must sign this transaction. The ETH then goes to the wallet of the owner, or to therecipientof 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.
- Craft the refresh: Use the
refresh-reportmethod. Any address can sign and pay for it. The address does not need a position. - Wait for the transaction: Broadcast it and wait until it is mined.
- 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.
| Step | Contract | Function |
|---|---|---|
| Move a token out of the call forwarder | Strategy | safeTransferERC20(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.
| Contract | Address on Hoodi |
|---|---|
| Strategy | 0xbF4797De82787A60101e5e45CEc7f29b27d83D98 |
| STV pool | 0xC6B9509E24F9aE488eDd3dCD488559f85678C552 |
| Pool withdrawal queue | 0xdded18c85c10B96b4B6eB2Ba70016F510bE4C902 |
Before you sign, make sure that payload.to is the expected contract:
| Action | payload.to |
|---|---|
stake, claim, unstake, withdraw, burn-wsteth, withdraw-pool | Strategy |
claim-pool-withdrawal | Pool withdrawal queue |
refresh-report | Lido 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
stakeandwithdraw-pool. When the report is stale, the API returns the reasonVaultReportStale. Send therefresh-reportaction, 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
400with the requested amount and the available amount.
The full list is in Endpoints, Errors.
API interaction
All eight actions use the same four steps.