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
RepayObligationLiquidity
Does not require RefreshReserve as it is impossible to worsen an obligation’s health by repaying.
cToken Instructions:
DepositReserveLiquidity
Deposit funds into the reserve, mint cToken
No need to escrow the cTokens in the CollateralSupplyAddress
Relies on cToken:Token Ratio
WithdrawObligationCollateral
Withdraw Funds, burn cTokens
Relies on cToken:Token Ratio
Monitoring/Misc Instructions
RefreshReserve
Update the price of every reserves, usually done before RefreshObligation
Pulls Oracle Prices
Updates 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
RefreshObligation
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.
Notes:
RefreshReserve/RefreshObligation used to be required for all transactions, but was removed to reduce oracle reliance after Jan2022’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 requires that reserves are refreshed.
RefreshReserve → RefreshObligation (repeated through all the positions) requires a lot of memory, which is a Solana limit, and thus limits our positions to 6.