StHYPEWithdrawalModule.sol
Last updated
Was this helpful?
Last updated
Was this helpful?
This page documents the Public & External Functions for the Withdrawal Module contract in the Stake Exchange (STEX) AMM Architecture.
The Withdrawal Module is responsible for managing the external use of reserves in Stake Exchange
Depositing Native Token Reserves (token1)
in a lending and borrowing protocol for extra yield
Initiating unstake operations for LST Reserves (token0
) to redeem them back to Native Token (token1
) at the true rate
The way these operations get triggered is programmable- and in the case of stHYPE AMM we use an offchain keeper to
Trigger LST unstaking flexibly.
This is because stHYPE AMMs native integration into the stHYPE Overseer ensures that new HYPE staked is routed to STEX AMM instantly- meaning pool reserves are kept denominated in HYPE if there are net new stakers vs instant withdrawals over a period of time. We would not get this efficiency if we unstaked at swap time. This is because once an LST is sent to the Withdrawal Queue it is illiquid and not able to be cancelled- HYPE reserves wouldn't get back to the pool until the stHYPE Queue settles deposits & withdrawals which happens every 24 hours. The considerations are covered in the Stake Exchange Whitepaper.
Deposit Native Tokens in Lending Markets flexibly.
stHYPE AMM allows for multiple lending markets to be whitelisted under timelock: hypurrFi, Hyperlend, HyperDrive, Euler, etc. Mediating exposure to new lending markets requires flexibility in exposure- and not putting 100% of the pool's HYPE reserves in external markets by default.
The Withdrawal Module is also responsible for managing the withdrawal lifecycle for the pool & exiting LPs who do not chose the instant LP withdrawal option.
Note: The above graphic is simplified to show the movement of funds between the pool and external reserves integrations- while in reality the external functions the keeper uses for moving funds between the pool and both the Lending Module and Unstaking Queue are contained in the Withdrawal Module contract.
Note: Functions related to LST withdrawals are specific to the implementation of stHYPE AMM as it integrates with the Overseer contract for stHYPE withdrawals.
Note: This implementation is only valid for LST protocols where slashing cannot occur after a withdrawal is initiated through the native withdrawal queue.
Parameters:
_amountToken0
: stHYPE amount to unstake
_recipient
: Future claim recipient
Checks:
Can only be called by StexAMM, called during the withdraw()
function when _isInstantWithdrawal
is set to False
and _amountToken0 > 0
.
Flow:
STEXAMM Liquidity Module calls this function to create an LP Withdrawal Request when an LP calls withdraw()
and wants to wait for their LST shares to convert to Native Token at the true rate.
Creates LPWithdrawalRequest
record
Tracks cumulative LP withdrawal amount cumulativeAmountToken1LPWithdrawal
.
LP has a claim to the exact amount of Native Token at the true rate at the time the claim was initiated
Events:
emit LPWithdrawalRequestCreated(uint256 id, uint256 amountToken1, address recipient)
Parameters:
_idLPQueue
: Withdrawal request ID, emitted during burnToken0AfterWithdraw()
Checks:
There is sufficient claimable balance
The Withdrawal has not been claimed already
Claim time priority eligibility: there is enough token0
for all LP Withdrawal Requests filed before this request to also claim.
Events:
emit LPWithdrawalRequestClaimed(uint256 id)
Note: Anyone can call this function, automatically transferring the corresponding Native Token (Token1
) to the recipient
Note: If there is slashing that can occur when a Withdrawal Request in pending in the withdrawal queue- this accounting method is invalid- and this withdrawal module contract should not be used
This function can be called by anyone, and is necessary to:
Update the Native Token claimable by Pending LP Withdrawal Requests
Send Native Token not marked for LP Withdrawals back to the pool reserves
Flow:
Processes pending withdrawals
Use leftover token to replenishes pool reserves
Updates:
_amountToken0PendingUnstaking
amountToken1PendingLPWithdrawal
amountToken1ClaimableLPWithdrawal
cumulativeAmountToken1ClaimableLPWithdrawal
Variable Overview:
_amountToken0PendingUnstaking
- tracks total LST balance pending unstaking. Includes both Pending Native Tokens that will be sent to exited LPs and the pool.
Only updated on unstakeToken0Reserves()
; and update()
.
amountToken1PendingLPWithdrawal
- pending exited LP claims that are not ready to be claimed yet. Native Token owed to LPs who have burned their position.
Increased when an LP Withdrawal is initiated after burning the LP token burnToken0AfterWithdraw()
; decreased an LP claims their Native Token balance claim();
decreased when LP Withdrawals become mature during update()
.
amountToken1ClaimableLPWithdrawal
- pending exited LP Native Tokens that are ready to be claimed.
Only updated on LP claim claim()
; and update()
.
cumulativeAmountToken1ClaimableLPWithdrawal
- a cumulative growing tracker of all matured claims that have become liquid for LPs. Does not reduce when an LP claims their Native Token.
Only updated on update()
.
Lending related functions in Withdrawal Module
are done through calls to Lending Module.
This standardizes functions for the Withdrawal Module across different lending markets. New lending integrations can be made through the lending module upgrade process, and don't require redeploying the STEX pool or Withdrawal Module.
token1
) to lending strategy using lendingModule
Parameters:
_amountToken1
: Native Token to deposit
Checks:
Can only be called by owner
Flow:
Transfers Native Token (token1)
to lending module
Tracks balance of Native Token (token1
) deposited in the lending protocol.
Parameters:
_amountToken1
: amount of Native Token to remove from the lending protocol
_recipient
: the address to send the withdrawn funds in the case of STEX AMM calling the function
Checks:
Can either be called by owner or StexAMM
No reentrancy in StHYPEWithdrawalModule
No reentrancy in STEX AMM's Sovereign Pool
Flow:
Call withdraw()
functions on the lending module
Funds are transferred to either pool when caller is owner, otherwise they are transferred to recipient as specified by STEXAMM (directly to the user making an LP withdraw if the token does not need to be unwrapped; to the DepositWrapper if the token needs to be unwrapped before before sending to the exited LP)
token0
) reservesChecks:
Can only be called by owner
_unstakeAmountToken0
sanity checks occur in STEXAMM
Parameter:
_unstakeAmountToken0
: amount of token0
to send to the unstake queue
Flow:
Redeems LST (token0
) in pool through the integrated LST withdrawal mechanism
Tracks pending unstaking balance
Parameters:
_stex
: STEXAMM contract address
Checks:
Can only be set once
Valid contract address
Events:
emit STEXSet(_stex)
The integrated lending market is upgradeable under timelock using a proposal proccess.
NOTE: The lending module is able to hold a potentially uncontrained amount of the pool's token1 reserves, a faulty lending module, or insolvent integrated market, can result in a partial or full loss of funds stored in the lending module.
Purpose: Start process of upgrading lending module under timelock
Checks:
Only callable by owner
Timelock is between 3 and 7 days
No reentrancy in STEX AMM's Sovereign Pool
Events:
emit LendingModuleProposed(_lendingModule, block.timestamp + _timelockDelay)
Purpose: Cancel the lending module prososal before its executed
Checks:
Only callable by owner
There is an active lending module upgrade proposal
Flow:
lendingModuleProposal
deleted
Events:
emit LendingModuleProposalCancelled()
Purpose: Set the lending module once the active proposal has surpassed timelock
Checks:
Timelock delay has completed
There is an active lending module change proposal
Flow:
If there was a previous lendingModule
set with non-zero `assetBalance()`, withdraw funds from previous lendingModule
to STEX AMM's pool.
Update lendingModule
lendingModuleProposal
deleted
Events:
emit LendingModuleSet(address(lendingModule))
NOTE: This is a custom getter function, which is in perfect sync with the contract's ETH balance, so that accounting is accurate even before update
gets called.
NOTE: This is a custom getter function, which is in perfect sync with the contract's ETH balance, so that accounting is accurate even before update
gets called.
token0
In the case of a rebase token- this function returns 1:1
In the case of a rebase token- this function returns 1:1
Purpose: returns the underlying token0 balance given a rebase token (token0) shares
Parameters:
_shares
: the shares value to convert to token balance
Returns:
balance associated with input shares value for token0
Purpose: returns the underlying token0 balance given a rebase token (token0) shares
Parameters:
_balance
: the token0 balance to convert to a shares value
Returns:
shares associated with input balance for token0
Purpose: Returns the share of token0 for an input address
Parameters:
_account
: address to measure the token0 shares of
Returns:
shares associated with input address
Purpose: return LP Withdrawal Request for a specific id
parameters:
_idLPWithdrawal
: the id of a LP withdrawal request, emitted during burnToken0AfterWithdraw()
return Struct:
recipient
: address that will receive the Native Token when claim()
is called by anyone with the corresponding withdrawal id
amountToken1
: amount of Native Token to be sent to recipient
cumulativeAmountToken1LPWithdrawalCheckpoint
: checkpoint used to enforce time priority on LP withdrawals. LP request cannot be claimed unless there is enough token1 to fulfill all pending LP Withdrawals made prior and enough to fill this one.