Protocol
Intelligence
Mevryx monitors liquidation opportunities across four DeFi lending protocols simultaneously. Each protocol has its own discovery mechanism, health accounting system, and liquidation mechanics — yet the platform surfaces all of them through a single normalized interface, ranked by real profitability.
This page documents exactly how Mevryx connects to each protocol: what data is fetched, how health is interpreted, and what makes each one different from a liquidator's perspective.
Normalization Layer
The core challenge of monitoring multiple protocols is that each one speaks a different language. Aave returns aggregated USD values directly from the contract. Compound computes health from per-asset Chainlink feeds. Euler denominates everything in a per-vault "unit of account" that can be either a stablecoin or ETH. Morpho uses an LLTV ratio instead of a health factor entirely.
Mevryx resolves this through a shared NormalizedPosition type. Every adapter, regardless of protocol, outputs the same structure — USD values, a health score, distance to threshold, and a net profit figure after gas costs. This means the ranking engine, the frontend, and the alert system never need to know which protocol a position came from.
Shared Type Fields
NormalizedPosition {
protocol: 'aave_v3' | 'compound_v3' | 'euler_v2' | 'morpho'
owner: string // wallet address
collateralAsset: string // e.g. "WETH", "MULTI", "wstETH"
borrowAsset: string // e.g. "USDC", "MULTI"
collateralValueUSD: number // always in USD
debtValueUSD: number // always in USD
healthScore: number // protocol-normalized — see below
distanceToThreshold: number // % price drop to liquidation
liquidationBonusPct: number // e.g. 0.05 = 5%
liquidationProfitNetUSD: number // gross profit minus gas cost
isProfitable: boolean
isHidden: boolean // true if oracle lag detected
needsFlashLoan: boolean // Aave only
isVerifiedCollateral: boolean // curated asset lists
}Aave V3
Per-BlockWatchlistAave V3 is the most data-efficient protocol to monitor. The contract's getUserAccountData() function returns a pre-computed health factor and aggregated USD values in a single call, meaning Mevryx doesn't need to calculate health independently — it comes straight from the protocol.
Position Discovery
Aave positions are tracked via a watchlist — a database of wallet addresses seeded from The Graph subgraph, refreshed every 6 hours. Every new Ethereum block triggers a multicall batch across all watched wallets, fetching their account data simultaneously.
Health Factor
Aave returns the health factor as a raw uint256 with 18 decimal places. Mevryx divides by 1e18 to get the decimal value. No recalculation is needed — the protocol does this internally using its own weighted liquidation thresholds per asset.
// From contract (18 decimals) healthScore = healthFactor / 1e18 // USD values (8 decimals, already in USD base currency) collateralValueUSD = totalCollateralBase / 1e8 debtValueUSD = totalDebtBase / 1e8
Liquidation Mechanics
Aave V3 caps each liquidation at 50% of the outstanding debt. This is a protocol rule to prevent full single-step liquidations. Combined with the mandatory flash loan (to source the repayment capital), the profit calculation accounts for both the 0.09% flash loan fee and gas costs.
grossProfit = (debtUSD × 0.5) × 0.05 // 5% bonus on half the debt flashLoanFee = (debtUSD × 0.5) × 0.0009 // 0.09% fee netProfit = grossProfit - flashLoanFee - gasCostUSD
Compound V3
Per-BlockWatchlistCompound V3 (Comet) operates a single-asset borrow market — all debt is in USDC. This makes debt accounting trivial, but health calculation is more involved: Mevryx must fetch each collateral asset's balance, its Chainlink price, and its per-asset liquidation factor on-chain to compute health from scratch.
Position Discovery
Like Aave, Compound positions are seeded from The Graph and stored in a watchlist. Every block triggers a multicall to the Comet contract — but the call structure is more complex because each position requires multiple sub-calls: borrow balance, liquidatability flag, and one balance call per supported collateral asset.
Health Factor Calculation
Compound doesn't return a health factor directly. Mevryx recomputes it from raw data: for each collateral asset, it fetches the USD price via the asset's Chainlink feed, multiplies by the asset's liquidateCollateralFactor, and sums across all assets. The result is divided by the USDC debt balance.
// Per-asset assetUSD = (balance / scale) × getPrice(priceFeed) / 1e8 liquidValue = assetUSD × liquidateCollateralFactor / 1e18 // Aggregate healthScore = Σ(liquidValue_i) / debtUSD
The contract also exposes an isLiquidatable() boolean. If this returns true while the computed health factor is still above 1.0, Mevryx overrides health to 0.99 — the protocol's own assessment takes precedence.
Euler V2
5-Min ScanSubgraphEuler V2 is a permissionless vault system — anyone can create a lending market for any asset. This means Mevryx cannot rely on a fixed contract address or a known set of assets. Instead, it enumerates all active positions from the Goldsky subgraph every five minutes, then queries each vault contract directly for health data.
Position Discovery
The Goldsky subgraph tracks all accounts that have active borrows across Euler's vault ecosystem. Each entry contains the subaccount address and the vault address — Mevryx parses these from packed binary data in the subgraph response, then batches on-chain health queries against each vault.
Health Factor Calculation
Euler's accountLiquidityFull(account, liquidation=true) returns all collateral values and the total liability value, already denominated in the vault's "unit of account" (which can be USDC, USDT, DAI, or WETH depending on the vault). Mevryx converts to USD as a final step.
// From vault contract
(collaterals[], collateralValues[], liabilityValue) = accountLiquidityFull(account, true)
// Health score
totalCollateralValue = Σ(collateralValues)
healthScore = totalCollateralValue / liabilityValue
// Convert to USD (unit of account dependent)
if (unitOfAccount == WETH):
valueUSD = rawValue / 1e18 × ethPrice
else:
valueUSD = rawValue / 1e18 // stablecoin UOALiquidation Bonus
Unlike Aave and Compound where the bonus is a fixed 5%, Euler's liquidation discount is set per vault via the maxLiquidationDiscount() function. Mevryx fetches this on-chain alongside health data and uses it in the profit calculation.
liquidationBonusPct = maxLiquidationDiscount / 10_000 liquidationProfitUSD = min(collateralUSD, debtUSD) × liquidationBonusPct liquidationProfitNetUSD = liquidationProfitUSD - gasCostUSD
Collateral Asset Identification
Because a single account can use multiple vaults as collateral simultaneously, Mevryx identifies the primary collateral as the vault with the largest USD value. The asset symbol is fetched from the ERC-20 contract and cached to avoid redundant RPC calls on subsequent scans.
accountLiquidity() on all watched positions every block — giving Euler positions near-real-time health updates despite the longer scan cycle.Morpho
5-Min ScanGraphQL APIMorpho is architecturally the most minimal of the four protocols — the core contract is intentionally simple, with no oracle logic or interest rate models inside the protocol itself. Health is defined purely by LLTV (liquidation loan-to-value), which is set per market at creation time and never changes.
Position Discovery
Morpho provides an official GraphQL API that exposes all positions with borrow shares greater than zero. Mevryx queries this for the top 5,000 positions by borrow size, then verifies each one on-chain via multicall to confirm the position is still open and adjust for any share drift since the API snapshot.
Health Factor Calculation
Morpho doesn't have a health factor — it uses LLTV. Mevryx maps this to the universal convention by computing health as the ratio of LLTV-adjusted collateral to outstanding debt. When this value crosses 1.0, the position is liquidatable.
lltvFloat = market.lltv / 1e18 // e.g. 0.77 for a 77% LLTV market healthScore = (collateralValueUSD × lltvFloat) / debtValueUSD // On-chain adjustment for share drift ratio = onChainBorrowAssets / apiBorrowAssets debtValueUSD = apiBorrowAssetsUsd × ratio
Liquidation Incentive Curve
Morpho's liquidation incentive is not a fixed percentage. It follows a curve based on the market's LLTV — lower LLTV markets (safer collateral) have higher incentives to attract liquidators for the rarer events. The formula implements Morpho's published liquidation cursor mechanism.
LIQUIDATION_CURSOR = 0.3 MAX_LIQUIDATION_INCENTIVE = 0.15 denominator = 1 - CURSOR × (1 - lltvFloat) incentive = min(MAX_INCENTIVE, 1 / denominator - 1) // Example: 77% LLTV → ~4.5% incentive // Example: 91.5% LLTV → ~3% incentive
Block-Level Health Monitoring
Between 5-minute scans, Mevryx tracks Morpho position health using borrow share changes as a proxy — if a position's borrow shares increase by more than 0.5% in a single block, it's flagged for priority refresh on the next scan cycle. This avoids fetching oracle prices every block while still catching fast-moving positions.
Profitability Scoring
With normalized positions from all four protocols, Mevryx ranks them using a composite priority score that balances two factors: how much profit is available right now, and how close the position is to the liquidation threshold.
// Priority score (stored in Redis sorted set) hfScore = 1_000_000 / healthScore // lower HF → higher score priorityScore = netProfitUSD × 0.6 + hfScore × 0.4
The 60/40 weighting intentionally prioritizes profit over urgency. A highly profitable position with HF 1.05 ranks above a marginal position at HF 1.001. This reflects real liquidation economics — gas costs and execution risk make marginal opportunities less attractive even if they're technically closer to the threshold.
Oracle Lag and Hidden Positions
Every 60 seconds, Mevryx compares live CoinGecko prices against on-chain Chainlink values for ETH, BTC, LINK, and USDC. If the divergence exceeds 0.5%, positions collateralized by affected assets are marked isHidden: true.
Hidden positions are those that would appear liquidatable using real market prices, but are not yet liquidatable on-chain because the Chainlink oracle hasn't updated. This is the core insight behind Mevryx: the oracle lag window is the early-warning signal that lets operators prepare before the liquidation is technically executable.