User Instructions

Interact program to program via these instructions, or refer to the GitHub link below:

DepositReserveLiquidityAndObligationCollateral (Supply)

  • Deposit reserve liquidity (Transfer) + mint cTokens (MintTo) + Transfer cTokens into CollateralSupplyAddress (Transfer)

  • Does not require RefreshReserve as it is impossible to worsen an obligation’s health by repaying.


  • Redeem cTokens from CollateralSupplyAddress

  • Exchange cTokens into Tokens using the cToken Rate

  • Requires RefreshReserve to ensure that the user is able to withdraw without defaulting their existing borrows

  • RefreshReserve → RefreshObligation → WithdrawObligationCollateralAndRedeemReserveCollateral


  • Bundled with Refresh Reserve

  • if “borrow_reserve.last_update.is_stale(clock.slot)? {” fails, reserve is considered stale (refreshreserve + borrow must be in the same slot)

  • RefreshReserve → RefreshObligation → Borrow


  • Does not require RefreshReserve as it is impossible to worsen an obligation’s health by repaying.

cToken Instructions:


  • Deposit funds into the reserve, mint cToken

  • No need to escrow the cTokens in the CollateralSupplyAddress

  • Relies on cToken:Token Ratio


  • Withdraw Funds, burn cTokens

  • Relies on cToken:Token Ratio

Monitoring/Misc Instructions


  • Update the price of every reserve, usually done before RefreshObligation

  • Pull Oracle prices

  • Update CumulativeBorrowRate to calculate interest paid since last refreshed block

  • Update the Obligation CumulativeBorrowRate to apply an increase in borrow value

  • Update cToken Rate for supply side users

  • Done 2x for every reserve, supply and borrow side


  • Done after RefreshReserves

  • Calculate individual obligations that ran the Withdraw or Borrow tx to calculate LTV before borrows

  • Assess whether the tx can go through based on account health


RefreshReserve/RefreshObligation used to be required for all transactions, but were removed to reduce oracle reliance after Jan 2022’s network issues.

Liquidator will call RefreshObligation before liquidating

However, borrow/withdraw has to check whether the obligation is refreshed in the SAME slot. But obligations require that reserves are refreshed.

RefreshReserve → RefreshObligation (repeated through all the positions) requires a lot of memory, which is limited by Solana, and thus limits our positions to 6.

Last updated