Repay and Withdraw Flow

Repay and Withdraw Flow

  • Repaying a Loan: A borrower (or anyone on their behalf) can repay a loan by calling repay(asset, amount, rateMode, onBehalfOf). The contract checks the user’s outstanding stable and variable debt for that asset. If amount is set to type(uint256).max, it will repay the full outstanding amount. The appropriate debt token contract is then invoked to burn the debt tokens equal to the repaid amount (reducing the borrower’s recorded debt). The reserve state is updated for interest accrual before and after this operation – repaying increases available liquidity, so updateState() and updateInterestRates() are called with liquidityAdded = amountRepaid, which will typically lower borrow rates and liquidity rate slightly. The actual asset tokens are transferred from the payer to the aToken contract (essentially returning liquidity to the pool). Finally, aToken.handleRepayment() is called – this might trigger any internal accounting needed on the aToken side (for Aave, this was used to redirect interest to the right places). A Repay event is emitted with the repaid amount. After repayment, the user’s health factor improves (since debt is reduced). If the loan is fully repaid (remainingDebt == 0), the user’s configuration is updated to mark they are no longer borrowing that asset. Repaying also triggers the incentives controller update via the debt token burn: the borrower’s reward accrual for that debt token pool will be updated (their debt balance goes down, so their share of future rewards is lower, but they keep any PRFI accrued so far).

  • Withdrawing Collateral: A user can withdraw their deposited asset by calling withdraw(asset, amount, to). If the amount is set to max, the user’s entire aToken balance for that asset will be withdrawn. The protocol first checks that after withdrawal, the user’s remaining collateral can still cover their current borrowings (if any) – this uses the oracle to ensure the user’s health factor stays ≥ 1. If the withdrawal would make the loan under-collateralized, it is rejected by ValidationLogic.validateWithdraw. Upon a valid withdrawal, the reserve is updated for interest (accrue up to current time) and interest rates are adjusted with liquidityTaken = amountWithdrawn (since liquidity is leaving the pool). If the user is withdrawing their full balance, the protocol also marks that asset as no longer being used as collateral in the user’s config (since they’ll have zero aTokens left). The aToken burn() function is then called to burn the user’s aTokens and transfer the corresponding underlying asset out to the specified address (the user’s wallet or another address they choose). A Withdraw event is emitted with the amount. This process effectively redeems the user’s underlying, including any interest earned (because the aTokens burned are valued with the latest liquidity index). From the rewards perspective, the aToken burn triggers the incentives controller to update the user’s balance in that reward pool. If the user fully exits, their amount in the Chef controller for that pool becomes 0, but any pending rewards they had earned remain available to claim (the system will not erase accrued rewards even if balance goes to zero). Thus, a user can withdraw and later still claim the PRFI tokens they accrued while they were supplying.

Last updated