EQ Lab develops a variety of different products on multiple blockchain platforms. Among others, there is am EVM-based decentralized lending protocol that allows users to take up to 20x leveraged long and short positions on crypto assets across different DEX-es and AMMs. In this article we will explore how this product utilizes binary heaps to handle margin calls.
The protocol is comprised of liquidity pools. Each pool consists of a quote asset (stablecoin) and a base asset (risk asset). For each pool there is a corresponding AMM pool where quote and base assets can be exchanged. Lending pools allow to deposit base or quote asset, go long or short (borrow the other asset with up to 20x leverage), withdraw base or quote asset, and close long/short positions.
Four indexes are calculated for each pool. They are baseCollateralCoeff, baseDebtCoeff, quoteCollateralCoeff, quoteDebtCoeff. These are used to determine interest rates.
There are three types of positions: Lend, Long, and Short When a user creates any of these positions a discounted balance is stored instead of the “real” balance. This is how it is calculated:
discountedBalance = realBalance / coeff
There are separate coefficients for Lend, Long and Short positions. For example if a Lend position is created by depositing quote asset the following calculation applies:
discountedQuoteAmount = realAmount / quoteCollateralCoeff
The calculation for Short and Long positions is as follows:
discountedBaseAmount = realAmount / quoteDebtCoeff
Short and Long positions are then stored in two separate collections. They are sorted in descending order of debtAmount/collateralAmount. For short positions this is calculated as baseAmount/quoteAmount, and for long positions the calculation is quoteAmount/baseAmount.
These sorted positions are stored in a Max binary heap.
Any user action that changes a position’s quoteAmount/baseAmount ratio triggers a recalculation of the binary heap such that the first element is always the riskiest position.
Interest rates are scaled proportionally to asset volatility and leverage. Total long leverage and total short leverage is calculated for each pool. Users who take up long or short positions pay interest fees to collateral providers. Fee accrual is done by changing baseCollateralCoeff, quoteCollateralCoeff coefficients. Fee write-off occurs by modifying the baseDebtCoeff and quoteDebtCoeff.
User action triggers a heap check of long and short positions leverages. Leverage is calculated for the riskiest position (heap root). It is then compared to the max leverage pool parameter. If the position’s leverage exceeds max leverage, the position is liquidated. In this case collateral is swapped and used to cover liabilities. The rest is then distributed between lenders. If there is not enough collateral to settle, the lenders cover the difference. These actions are performed by modifying baseCollateralCoeff or quoteCollateralCoeff. This way individual balances don’t need to be changed.
This design allows to run an automated liquidator as well as potentially implement no-liquidation systems in future versions of the protocol. It is more capital efficient compared to designs that implement collateral, debt and balances positions for each user because liquidity can be reused: the same capital can be used to go both long and short simultaneously. This could ultimately result in a superior product and user experience.