Development of Liquidation Protocol
Aave V3 loses a liquidator faster than you think. Under high network load, gas for liquidationCall rises to 400-600k gas units—at 80 gwei, that's 0.03-0.05 ETH in gas alone. If the spread between debt and collateral is smaller than this sum, liquidation becomes unprofitable, and the position stays in bad debt state. This is why liquidator incentive design is not a detail but the foundation of entire lending protocol solvency.
Liquidation Mechanics: Why Standard Approaches Fail
Health Factor and Liquidation Threshold
Each position has a health factor:
HF = Σ(collateral_i * LT_i) / total_debt
When HF < 1, the position is liquidatable. Liquidation threshold (LT) is set separately for each asset: ETH at 82.5%, USDC at 85%, more volatile assets at 65-75%. This means custom lending with exotic assets requires careful LT calibration based on historical volatility.
The "dust position" problem: if a position is small (debt $50), gas ($30-80) eats all profit. Liquidators ignore such positions—the protocol accumulates bad debt. Solutions: minimum debt threshold or flat fee component in incentive.
Liquidation Bonus and Large Position Problems
Standard approach: liquidators get liquidation bonus (5-10%) from liquidated collateral. Works for medium positions. For positions with >$10M collateral, liquidators can't liquidate all at once due to slippage—the asset price falls during sale, bonus is negated.
Aave V3 solves this with partial liquidation (up to 50% at a time) and close factor. For custom protocols, we implement dutch auction: bonus starts at 5% and grows over time until the position is liquidated. This minimizes overpayment under normal conditions and guarantees liquidation during stress.
Flash Loan Liquidations and MEV
Professional liquidators don't hold capital—they use flash loans. Scheme: take a flash loan of the asset, repay the position's debt, receive collateral with bonus, sell collateral, repay flash loan. All in one transaction, zero capital.
This means your protocol must be flash loan compatible. Specifically: liquidationCall must accept collateralAsset and debtAsset separately, return aToken or base asset per user choice, and not block calls from smart contracts.
MEV aspect: most liquidations are MEV-frontrun. Not necessarily bad for the protocol—liquidation happens anyway. But to protect "honest" liquidators, integrate Flashbots MEV Blocker or implement a private mempool for liquidations.
Liquidation Engine Architecture
Two-Level Liquidation System
We build two liquidation modes in one contract:
Mode 1—standard liquidation. Liquidator provides the asset to repay debt, receives collateral with bonus. Simple, gas-efficient, works for most positions.
Mode 2—auction liquidation. Activated for positions with collateral above a threshold (e.g., $500K). Dutch auction: starting collateral price = market price * (1 - max discount); price increases every N blocks. First liquidator willing to accept current price wins.
function getAuctionPrice(
uint256 startPrice,
uint256 startBlock,
uint256 priceIncreasePerBlock
) public view returns (uint256) {
uint256 elapsed = block.number - startBlock;
return startPrice + (elapsed * priceIncreasePerBlock);
}
Oracle Integration and Manipulation Protection
Liquidation logic depends critically on oracle prices. Chainlink is the primary source. For protection from stale data:
function _getPrice(address asset) internal view returns (uint256) {
(, int256 price, , uint256 updatedAt, ) = AggregatorV3Interface(feed).latestRoundData();
require(block.timestamp - updatedAt <= MAX_STALENESS, "Stale oracle");
require(price > 0, "Invalid price");
return uint256(price);
}
MAX_STALENESS is set per asset: ETH/USD updates every 27 seconds or at >0.5% deviation; exotic assets update less frequently. For assets without Chainlink, use Uniswap V3 TWAP with minimum 30-minute window.
Bad Debt Socialization
If the protocol accumulates bad debt (position becomes unliquidatable if collateral value falls below debt), you need a coverage mechanism. Options:
- Insurance module: separate pool of protocol tokens; stakers bear first loss
- Reserve factor: portion of interest income goes to reserves
- Bad debt socialization: loss spread across all LPs proportionally
Aave uses Insurance Module (Safety Module) with staked AAVE. Compound V3 uses reserve factor. We implement the approach matching the protocol's tokenomics.
Stack and Tools
| Layer | Technology |
|---|---|
| Contracts | Solidity 0.8.24, OpenZeppelin 5.x |
| Oracles | Chainlink AggregatorV3, Uniswap V3 TWAP |
| Flash loans | Aave V3 FlashLoanSimpleReceiver |
| Testing | Foundry fork mainnet, Echidna |
| Monitoring | The Graph subgraph, Tenderly Alerts |
| Deployment | Foundry forge script, Gnosis Safe |
Work Process
Analytics. Model stress scenarios: ETH drops 40% in 1 hour (like May 2021). Calculate parameters where LT/bonus keep protocol solvent.
Development. Liquidation engine + Chainlink integration + auction module. Parallel: off-chain liquidation bot for early protocol weeks (until external liquidators arrive).
Testing. Fork-test on Ethereum mainnet: simulate mass liquidations from March 2020 (Black Thursday). Verify bad debt doesn't accumulate under realistic scenarios.
Timeline Estimates
Basic liquidation module for embedding in lending protocol: 1-2 weeks. Autonomous liquidation protocol with dutch auction and bad debt socialization: 3-4 weeks. Including off-chain liquidation bot development: add 1 week.







