For the complete documentation index, see llms.txt. This page is also available as Markdown.

Ethena Cooldown

A plain adapter that reports the USDe owed to an account that is in the sUSDe unstaking cooldown.

A plain adapter that reports the USDe owed to an account that is in the sUSDe unstaking cooldown. When a holder calls cooldownShares / cooldownAssets on Ethena's StakedUSDeV2, the sUSDe is burned and the underlying USDe is moved to a silo, recorded against the holder until cooldownEnd passes and they unstake. While cooling, this value is invisible to wallet and receipt-token adapters.


Positions returned

A single leg per account — non-zero only while an unstake is in flight. Unlike the queue adapters, sUSDe keeps one cooldown record per account, so this is one leg whose isLocked toggles, not two legs:

Leg
PositionKind
isDebt
isLocked
Description

Pending cooldown

Supplied

false

toggles

Full pending USDe; isLocked=false once claimable, isLocked=true while cooling

The pending USDe is carried in balanceAsset. There is one cooldown per account, so the leg carries positionInstanceId = bytes32(0). The position is dropped if USDe is not registered in NAVCalculator, if the pending amount is zero, or if filtered out by assetFilter.


Balance calculation

Flowchart of the Ethena Cooldown balance adapter: read calls derive position legs into PositionBalance entries.
Ethena Cooldown adapter — how the underlying balances reported to the NAV Calculator are derived.

There is exactly one cooldown slot per account (a new cooldown adds to it), so no enumeration is needed — a single read gives the full pending amount, and a second read sets isLocked:

underlyingAmount is the full pending USDe, claimable once cooldownEnd passes; the protocol zeroes the slot on claim, so a closed or never-opened cooldown reads as 0. The leg is reported with isLocked=false iff block.timestamp >= cooldownEnd or cooldownDuration() == 0 (cooldown disabled); otherwise isLocked=true. The adapter checks the cheap cooldowns read first and bails before scanning the registered-asset list when there is nothing pending.


Identity

  • positionId: abi.encode(sUSDe) (static; the Ethena StakedUSDeV2 address)

  • positionKind: Supplied

  • positionInstanceId: bytes32(0) (one cooldown per account — no per-item handle)

  • Labels: the adapter implements positionLabels(positionId), returning ["Unstaking Cooldown", "sUSDe"] (surfaced only on the verbose read path; full breadcrumb = ["Ethena", "Unstaking Cooldown", "sUSDe"]).

sUSDe keeps a single cooldown record per account, so this adapter emits one leg under this positionId (not two). Its isLocked field toggles — false once claimable, true while still cooling — and the pending USDe rides in balanceAsset. The reconciliation key is keccak256(abi.encode(chainId, protocolSubId, positionId, balanceAsset.asset, positionKind))isLocked is a mutable per-leg attribute and is not part of the key, so this single leg keeps one stable key as its flag toggles true→false.


Constructor

Parameter
Description

stakedUSDe_

Ethena StakedUSDeV2 (sUSDe) contract, which holds the per-account cooldown record. Must be a contract

underlyingToken_

Asset positions are denominated in — USDe (what the cooldown pays on unstake)

navCalculator_

NAVCalculator address, used for asset-registry filtering. Must be a contract


Registration

Registered as a plain adapter with addBalanceAdapters([adapter]) and removed with removeBalanceAdapters([adapter]).

Last updated