LidoAdapter
Inherits: IStrategy, IProtocolAdapter, IAdapterOperator, ILidoAdapter
Title: LidoAdapter
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from Lido (https://github.com/lidofinance/core)
Diamond facet adapting a Lido staking position into a Lattice vault strategy under the
buffer model. Implements IStrategy (funds routing), IProtocolAdapter (sidecar),
and ILidoAdapter (Lido config + async-queue keeper). The asset is WETH; native ETH
is only an intermediate hop (WETH → ETH → stETH → wstETH on deploy, and the reverse on
the async exit). Because Lido withdrawals are an async queue, the synchronous
IStrategy.withdraw is served from an idle WETH buffer and is shortfall-honest; the slow
Lido-queue exit runs out-of-band via requestWithdrawal / claimWithdrawal. All logic
lives in LidoAdapterLib.
Provenance: Lido stETH / wstETH / WithdrawalQueue (https://github.com/lidofinance/lido-dao) +
canonical WETH9 (https://github.com/gnosis/canonical-weth). The facet's own payable
receive() serves STANDALONE hosting only — behind a diamond, empty-calldata ETH routes to the
cut Receive facet, and the WETH unwrap goes through the stipend-safe WETHUnwrapper.
Notes:
- lattice-version: 0.1.0
- lattice-source: Lattice original
Functions
asset
Returns the address of the underlying asset this strategy manages.
function asset() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
totalAssetsManaged
Returns the current total asset balance managed by this strategy.
This value is trusted by the StrategyManager and VaultCore for accounting. Strategy implementations MUST report accurate balances to avoid mispricing vault shares.
function totalAssetsManaged() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
withdraw
Withdraws amount of the underlying asset to to.
Called by the StrategyManager during rebalancing to recall excess allocations. The strategy is responsible for executing the ERC-20 transfer.
function withdraw(uint256 amount, address to) external virtual override returns (uint256 withdrawn);Parameters
| Name | Type | Description |
|---|---|---|
| amount | uint256 | Amount of underlying asset to withdraw. |
| to | address | Recipient address (typically the vault). |
Returns
| Name | Type | Description |
|---|---|---|
| withdrawn | uint256 | Actual amount transferred (may be less if strategy has slippage). |
deploy
Sweeps the adapter's idle asset balance into the external protocol.
Required because the vault PUSHES funds via a bare ERC-20 transfer (no callback).
Reverts ProtocolAdapterNothingToDeploy if the idle balance is zero.
function deploy() external virtual override returns (uint256 deployed);Returns
| Name | Type | Description |
|---|---|---|
| deployed | uint256 | The amount swept into the protocol. |
harvest
Claims reward tokens from the protocol and forwards them RAW (no swap) to the configured recipient.
No-op: Lido yield accrues in the wstETH→stETH rate (already in NAV), not a claimable
reward token. Use harvestToken to forward a specific stray (airdropped) token.
function harvest() external virtual override;emergencyWithdraw
Fully exits the protocol position and returns all recovered assets to the vault.
Intended for the emergency path; callable by an authorized guardian/admin even when the adapter is paused.
function emergencyWithdraw() external virtual override returns (uint256 recovered);Returns
| Name | Type | Description |
|---|---|---|
| recovered | uint256 | The amount returned to the vault. |
isPaused
Returns true when the adapter is paused or emergency-stopped, or the external
protocol reports the asset paused/frozen. When true, deploy() must be a no-op
path (revert), so a paused protocol cannot brick rebalance().
function isPaused() external view virtual override returns (bool);Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
healthFactor
Returns the current health factor (WAD, 1e18 == 1.0) of the adapter's position.
Supply-only adapters return type(uint256).max (no debt). Leverage adapters return
collateralValue * liquidationThreshold / debtValue.
function healthFactor() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
minHealthFactor
Returns the configured minimum health factor (WAD) the adapter must not breach.
function minHealthFactor() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
rewardRecipient
Returns the address rewards are forwarded to.
function rewardRecipient() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
setOperator
Sets the authorized operator permitted to call deploy/withdraw/harvest.
Admin-gated (DEFAULT_ADMIN_ROLE). Rejects address(0); emits
IProtocolAdapter.OperatorSet.
function setOperator(address operator_) external virtual override;Parameters
| Name | Type | Description |
|---|---|---|
| operator_ | address | The new operator (typically the StrategyManager diamond). |
operator
Returns the authorized operator (zero until wired).
function operator() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
reentrancyGuardEntered
True while a guarded op is executing — mirrors StrategyManager so VaultCore can reject share-price-sensitive ops mid-deploy/withdraw (read-only reentrancy guard).
function reentrancyGuardEntered() external view virtual returns (bool);Returns
| Name | Type | Description |
|---|---|---|
| <none> | bool |
weth
Returns the WETH token (the adapter's asset and idle buffer).
function weth() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
lido
Returns the Lido stETH token.
function lido() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
wstETH
Returns the wstETH wrapper the staked position is held as.
function wstETH() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
withdrawalQueue
Returns the Lido withdrawal queue the slow leg routes through.
function withdrawalQueue() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
vault
Returns the Lattice vault funds are returned to on withdraw/emergency.
function vault() external view virtual override returns (address);Returns
| Name | Type | Description |
|---|---|---|
| <none> | address |
bufferBalance
Returns the idle WETH buffer balance the synchronous withdraw is served from.
function bufferBalance() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
stakedWstETH
Returns the wstETH balance currently staked in Lido.
function stakedWstETH() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
pendingWithdrawalAssets
Returns the total stETH currently sitting in pending (unclaimed) withdrawal requests.
Counted in NAV so funds in-flight through the queue are not lost from accounting.
function pendingWithdrawalAssets() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
pendingRequestCount
Returns the number of pending (unclaimed) withdrawal requests.
function pendingRequestCount() external view virtual override returns (uint256);Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
pendingRequestAt
Returns the pending withdrawal-request id at index.
function pendingRequestAt(uint256 index) external view virtual override returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| index | uint256 |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |
requestWithdrawal
Unwraps wstAmount of wstETH to stETH and enqueues it in the Lido withdrawal queue
(admin/keeper). Records the resulting request id + stETH amount as pending so NAV is
unchanged by the move. The ETH is claimable later via claimWithdrawal.
function requestWithdrawal(uint256 wstAmount) external virtual override returns (uint256 requestId);Parameters
| Name | Type | Description |
|---|---|---|
| wstAmount | uint256 | The amount of wstETH to unwrap and enqueue. |
Returns
| Name | Type | Description |
|---|---|---|
| requestId | uint256 | The Lido withdrawal-request id created. |
claimWithdrawal
Claims a finalized withdrawal request (permissionless/keeper): pulls the owed ETH from the queue and wraps it 1:1 into the WETH buffer, clearing the request from pending.
function claimWithdrawal(uint256 requestId) external virtual override returns (uint256 ethReceived);Parameters
| Name | Type | Description |
|---|---|---|
| requestId | uint256 | The id of the finalized pending request to claim. |
Returns
| Name | Type | Description |
|---|---|---|
| ethReceived | uint256 | The native ETH claimed and wrapped into the buffer. |
setRewardRecipient
Sets the reward recipient (admin only). Lido yield accrues in the wstETH→stETH rate,
not a claimable reward token, so this only governs stray-token sweeps in harvest().
function setRewardRecipient(address recipient) external virtual override;Parameters
| Name | Type | Description |
|---|---|---|
| recipient | address |
harvestToken
Forwards the adapter's entire balance of a stray (airdropped) token raw to the
reward recipient (admin/keeper). The three core tokens (WETH/stETH/wstETH) are
rejected so a sweep can never drain the buffer or the staked position.
function harvestToken(address token) external virtual;Parameters
| Name | Type | Description |
|---|---|---|
| token | address |
receive
Accepts native ETH when hosted STANDALONE (unwrapper return, Lido queue payout). Behind a diamond this is never dispatched — the diamond's zero-selector route runs the Receive facet instead. No logic: the calling library re-wraps the ETH into WETH.
receive() external payable;exportSelectors
ERC-8153 selector export: this facet's cuttable selectors, tightly packed (4 bytes each).
Excludes exportSelectors() itself (0x0ef22643) - it is never cut into a diamond. Order matches
forge inspect LidoAdapter methodIdentifiers (alphabetical by signature); kept in exact parity by
ExportSelectorsParityTest. receive() has no selector and is not exported (it serves standalone
hosting only; see the contract NatSpec). Chunks:
asset() 0x38d52e0f
bufferBalance() 0x1298f13c
claimWithdrawal(uint256) 0xf8444436
deploy() 0x775c300c
emergencyWithdraw() 0xdb2e21bc
harvest() 0x4641257d
harvestToken(address) 0x0bb18dc1
healthFactor() 0x22841f01
isPaused() 0xb187bd26
lido() 0x23509a2d
minHealthFactor() 0xe1b4264c
operator() 0x570ca735
pendingRequestAt(uint256) 0x978e5f31
pendingRequestCount() 0xe0abba57
pendingWithdrawalAssets() 0xb5149a61
reentrancyGuardEntered() 0xd2c725e0
requestWithdrawal(uint256) 0x9ee679e8
rewardRecipient() 0x17f33340
setOperator(address) 0xb3ab15fb
setRewardRecipient(address) 0xe521136f
stakedWstETH() 0x4aedacb4
totalAssetsManaged() 0x613c822b
vault() 0xfbfa77cf
weth() 0x3fc8cef3
withdraw(uint256,address) 0x00f714ce
withdrawalQueue() 0x37d5fe99
wstETH() 0x4aa07e64
function exportSelectors() external pure virtual returns (bytes memory selectors);Returns
| Name | Type | Description |
|---|---|---|
| selectors | bytes |