Skip to main content

StETHRedeemManager

Title: StETHRedeemManager

Abstract contract implementing EIP-7540 Asynchronous ERC-4626 Tokenized Vaults. LP shares are burned immediately on requestRedeem; WETH is delivered asynchronously in FIFO order as Lido withdrawal claims arrive. Supports partial fulfillment: a request can receive a portion of its WETH now and the remainder from future Lido claims.

Actors:

  • owner - whose shares are burned on requestRedeem.
  • controller - controls when and to whom assets are claimed.
  • operator - approved by owner/controller to act on their behalf.

Flow:

  1. Owner (or operator for owner) calls requestRedeem(shares, controller, owner). Shares burned immediately; a request record is created for controller.
  2. As ETH arrives from Lido claims, _serveRedeemRequests allocates WETH to the oldest pending requests first (FIFO). Partial allocation is supported: _redeemHead advances only when a request is fully allocated.
  3. Controller (or operator for controller) calls claimRedeem(receiver, controller) which transfers all currently claimable WETH for that controller to receiver.

Accounting invariants:

  • _pendingRedeemAssets = sum of (assets - claimableAssets) for all requests. Subtracted from totalAssets() so remaining LPs see the correct share price.
  • _reservedRedeemAssets = sum of (claimableAssets - claimedAssets) for all requests. Excluded from swap liquidity and from totalAssets().

Functions

setOperator

Grant or revoke operator privileges for msg.sender as controller. Operators can call requestRedeem and claimRedeem on behalf of the controller.

function setOperator(address operator, bool approved) external returns (bool);

Returns

NameTypeDescription
<none>boolAlways true (EIP-7540 compliance).

isOperator

Returns whether operator is approved to act on behalf of controller.

function isOperator(address controller, address operator) public view returns (bool);

requestRedeem

Burn shares from owner and register an async redemption request. The WETH payout is delivered asynchronously (FIFO) as Lido withdrawal claims arrive. Caller must be owner or an approved operator for owner.

function requestRedeem(uint256 shares, address controller, address owner)
public
virtual
returns (uint256 requestId);

Parameters

NameTypeDescription
sharesuint256Vault shares to redeem.
controlleraddressAddress that will control when/to whom assets are claimed.
owneraddressAddress whose shares are burned.

Returns

NameTypeDescription
requestIduint256Global ID for this request (use with claimRedeem).

claimRedeem

Transfer all currently claimable WETH for controller to receiver. Caller must be controller or an approved operator for controller.

function claimRedeem(address receiver, address controller) public virtual returns (uint256 totalClaimed);

Parameters

NameTypeDescription
receiveraddressAddress to receive the WETH.
controlleraddressThe controller whose claimable assets are claimed.

Returns

NameTypeDescription
totalClaimeduint256Total WETH transferred (0 if nothing is currently claimable).

redeemRequestIds

Returns all request IDs controlled by controller (including fully claimed ones).

function redeemRequestIds(address controller) external view returns (uint256[] memory);

redeemRequest

Returns the full status of a single request.

function redeemRequest(uint256 requestId)
external
view
returns (uint256 assets, address controller, uint256 claimableAssets, uint256 claimedAssets);

redeemQueueLength

Total number of requests ever created (includes fully claimed ones).

function redeemQueueLength() external view returns (uint256);

reservedRedeemAssets

WETH currently reserved for allocated (but not yet claimed) redeem requests. This WETH is excluded from swap liquidity.

function reservedRedeemAssets() external view returns (uint256);

pendingRedeemRequest

EIP-7540: assets still pending allocation for a specific request. Returns 0 if controller does not match the request's controller.

function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256);

claimableRedeemRequest

EIP-7540: assets claimable but not yet claimed for a specific request. Returns 0 if controller does not match the request's controller.

function claimableRedeemRequest(uint256 requestId, address controller) external view returns (uint256);

Events

OperatorSet

Emitted when a controller grants or revokes operator status (EIP-7540).

event OperatorSet(address indexed controller, address indexed operator, bool approved);

RedeemRequested

Emitted when an LP submits a redemption request.

event RedeemRequested(
uint256 indexed requestId,
address indexed controller,
address indexed owner,
uint256 shares,
uint256 assets
);

Parameters

NameTypeDescription
requestIduint256Global ID assigned to this request.
controlleraddressAddress that controls claiming for this request.
owneraddressAddress whose shares were burned.
sharesuint256Vault shares burned.
assetsuint256WETH amount promised.

RedeemClaimed

Emitted when claimable WETH is transferred to a receiver.

event RedeemClaimed(address indexed receiver, address indexed controller, uint256 assets);

Parameters

NameTypeDescription
receiveraddressAddress that received the WETH.
controlleraddressController whose claimable assets were claimed.
assetsuint256Amount of WETH transferred.

Errors

NotAuthorized

error NotAuthorized();

MinSharesRequired

error MinSharesRequired(uint256 shares, uint256 minimum);

InsufficientClaimable

error InsufficientClaimable();

Structs

RedeemRequest

One entry per redemption request.

struct RedeemRequest {
uint256 assets; // total WETH owed (fixed at requestRedeem time)
address controller; // address that controls when/to whom assets are claimed
uint256 claimableAssets; // WETH allocated so far (may be partial)
uint256 claimedAssets; // WETH already transferred to a receiver
}