Skip to main content

BorrowCap

Git Source

Per-block borrow cap using dual LX/LY accumulators to mitigate TWAP lag attacks.

Tracks X-side and Y-side debt separately in L units. BORROW_L increases both sides. On new block, uses previous block's last known totals as baseline. Checks delta on every call. The per-block budget is: activeLiquidity × borrowCapBips / 10000. borrowCapBips is per-pair configurable via configure(); when unconfigured (0), it defaults to DEFAULT_BORROW_CAP_BIPS (500 = 5%). The sqrt(1.5) worst-case factor (k ≈ 1.2247) remains as a constant safety margin on X/Y borrow conversions to L-equivalents. Both the baseline and current values are stored as inflated L-equivalents (i.e. with the sqrt(1.5) worst-case factor already applied to X/Y components). Because the delta is computed as currentLX - baselineLX, the inflation on existing borrows cancels out, while the inflation on new borrows is preserved: baseline = L₁ + X₁ · k (k = worst-case conversion factor) current = L₂ + X₂ · k delta = (L₂ - L₁) + (X₂ - X₁) · k So a new X borrow of size dX contributes dX · k to the delta, not raw dX.*

State Variables

DEFAULT_BORROW_CAP_BIPS

uint256 constant DEFAULT_BORROW_CAP_BIPS = 500;

SQRT_BIPS

uint256 constant SQRT_BIPS = 10_000;

SQRT_WORST_CASE_BIPS

uint256 constant SQRT_WORST_CASE_BIPS = 12_247;

Functions

checkBorrowCap

Check that the per-block borrow cap has not been exceeded.

Computes LX and LY from raw borrow totals and oracle prices, then checks delta against the per-block cap. On new block, uses previous block's lastKnownLX/LY as the baseline snapshot. Repays lower the baseline.

function checkBorrowCap(
State storage state,
uint256 totalBorrowL,
uint256 totalBorrowX,
uint256 totalBorrowY,
uint256 sqrtPriceMinQ72,
uint256 sqrtPriceMaxQ72,
uint256 activeLiquidity
) internal;

Parameters

NameTypeDescription
stateStateper-pair borrow cap state
totalBorrowLuint256pair-level total BORROW_L assets
totalBorrowXuint256pair-level total BORROW_X assets
totalBorrowYuint256pair-level total BORROW_Y assets
sqrtPriceMinQ72uint256worst-case minimum sqrt price (for X-side deflation)
sqrtPriceMaxQ72uint256worst-case maximum sqrt price (for Y-side inflation)
activeLiquidityuint256active liquidity used to compute the cap

configure

function configure(State storage state, uint16 _borrowCapBips) internal;

computeLX

Compute the X-side debt in L units with worst-case sqrt(1.5) deflation.

LX = totalBorrowL + convertXToL(totalBorrowX, sqrtPriceMin * SQRT_BIPS / SQRT_WORST_CASE_BIPS)

function computeLX(
uint256 totalBorrowL,
uint256 totalBorrowX,
uint256 sqrtPriceMinQ72
) private pure returns (uint256);

computeLY

Compute the Y-side debt in L units with worst-case sqrt(1.5) inflation.

LY = totalBorrowL + convertYToL(totalBorrowY, sqrtPriceMax * SQRT_WORST_CASE_BIPS / SQRT_BIPS)

function computeLY(
uint256 totalBorrowL,
uint256 totalBorrowY,
uint256 sqrtPriceMaxQ72
) private pure returns (uint256);

Errors

BorrowCapExceeded

error BorrowCapExceeded();

InvalidBorrowCapConfig

error InvalidBorrowCapConfig();

Structs

State

struct State {
uint64 lastBlock;
uint16 borrowCapBips;
uint128 startOfBlockLX;
uint128 startOfBlockLY;
uint128 lastKnownLX;
uint128 lastKnownLY;
}