Algorithms
Paying Interest
Below is a high-level overview of how the system pays interest for all exclusive pools, followed by the details of each step.
1. Sort Exclusive Pools by Liquidity
- Retrieve a list of all active pools.
- Calculate each pool’s liquidity (
token0Reserves * token1Reserves
). - Sort pools in descending order based on this liquidity.
2. Pay Interest on Each Pool
After sorting, the contract iterates over each pool (from highest to lowest liquidity):
-
Determine Amount to Pay
CallstryPayingInterestInRatio
to figure out:- How many tokens (token0 and token1) the pool must pay.
- Whether the pool can fully pay, partially pay, or is forced to liquidate due to insufficient reserves.
-
Update Main Pool
After determining the token0 and token1 spent by the exclusive pool, the contract increases the main pool reserves accordingly. -
Prepare State Updates
The result (return data) for each exclusive pool is cached until all pools are processed.
3. Finalize Pool Updates
Once each pool has been tested for interest payment:
-
Liquidation or Reserve Update
- If a pool is marked for liquidation, it is removed from the active pool list immediately.
- If the pool can remain active:
- Its new reserves are stored.
- The pool’s index is updated if necessary.
- An event indicating successful payment (
ExclusivePoolInterestPaid
) is emitted.
-
Check Minimum K
- If the pool’s updated K (
newEpReserve0 * newEpReserve1
) is still below itsminimumK
, the contract attempts an arbitrage root solution:- If no solution exists, the pool is liquidated.
- If a solution exists, the pool’s reserves are adjusted accordingly, and the main pool is updated to reflect any
dx
ordy
from the arb trade.
- If the pool’s updated K (
4. Clean Up Liquidated Pools
Any pool that was liquidated is:
- Marked with
owner = address(0)
in storage (considered “dead”). - Removed from the
activePoolIds
array. - Has its final token0 and token1 reserves added back into the main pool.
5. Return Final Data
The function returns:
newMainPoolReserve0
andnewMainPoolReserve1
: The updated main pool reserves after all interest payments and potential liquidations.totalLiquidityLiquidated
: The total amount of liquidity removed (across all liquidated pools).totalPools
: The total count of pools that remain active.
Function: tryPayingInterestInRatio
This helper function (used in Step 2 above) calculates how much an exclusive pool can pay toward interest (in ratio) and determines if the pool must be liquidated.
-
Fetch Pool Info
Reads the exclusive pool’s data (reserves,minimumK
, etc.) from storage to understand the pool’s current state. -
Compute Interest Owed
- Calculates the liquidity (
rkOwedToInterestPayments
) the pool must pay, using:- Elapsed time
- Interest rate
- Flat fee
- Constructs the
targetK
(target product of reserves in the main pool after payment).
- Calculates the liquidity (
-
Figure Out Token Amounts
- Uses the pool’s
interestPaymentRatio64x64
(or the appropriate EDGAP ratio) to compute how many tokens (token0Amount
,token1Amount
) need to be spent. - Ensures no overflow by handling edge cases for division.
- Uses the pool’s
-
Check Payment Feasibility
- If the pool can fully pay the required amounts, it spends them directly.
- If both tokens are insufficient, the function indicates a liquidation.
- If only one token is insufficient, tries a partial coverage strategy with the other token.
-
Ensure No Underflow
- Adjusts any payment amounts exceeding the pool’s actual reserves.
- Avoids negative reserves (underflow).
-
Return Outcome
Returns a struct that includes:token0Spent
,token1Spent
: How many tokens are spent to cover the interest.newEpReserve0
,newEpReserve1
: Updated pool reserves.liquidate
: Whether liquidation is required.liquidityOwed
: The amount of liquidity the pool must contribute.- Misc. data:
poolId
,originalAssetRatio64x64
,minimumRk
, etc.
Overall Flow Summary
- Sort all exclusive pools by their liquidity.
- Iterate through each sorted pool, calculating its required interest payment with
tryPayingInterestInRatio
. - Apply each pool’s payments to the main pool.
- Determine liquidation or continued operation:
- If liquidation, remove the pool from active storage and transfer its reserves to the main pool.
- Otherwise, update the pool’s reserves and index.
- Attempt arb root solution if a pool’s
K
falls belowminimumK
. If no solution is found, liquidate. - Clean up all liquidated pools, zero out their storage data, and remove them from the active list.
- Return the final main pool reserves, total liquidity liquidated, and remaining number of pools.
This ensures all pools either pay the required interest or are liquidated if they cannot meet their obligations.