How close a position is to liquidation, in one number
The Aave Health Factor Checker reads any wallet’s Aave V3 position and returns the health factor, total collateral, total debt, available borrows, and liquidation threshold from one expression. It is built for borrowers, liquidation bots, and risk dashboards that need a fast read on how close a position is to liquidation without writing ABI files or remembering the right scaling for each field.
Key facts
- Reads Aave V3’s
getUserAccountData(user)in a single call, returning health factor, total collateral, total debt, available borrows, LTV, and liquidation threshold together. - Each field uses Aave’s own scaling: collateral and debt are 8 decimals, the health factor is 18 decimals, and LTV and liquidation threshold are 4-decimal ratios.
- Runs against the Aave V3 core Pool market on Ethereum, Base, and Polygon; isolated or permissioned markets and Aave V2 are out of scope.
- Every read hits the latest block at request time with no caching layer, and a wallet with no debt returns Aave’s max-integer health factor, which the tool displays as an infinity symbol instead of a 59-digit number.
How to use it
- Paste the wallet address you want to check into the form above.
- Pick the chain the Aave V3 position lives on.
- Run the query and read the health factor, collateral, debt, and thresholds in the result panel.
The result panel shows the health factor prominently, colored by risk band, along with total collateral and debt in USD, how much more the wallet could borrow, and the liquidation threshold and max LTV as percentages. Wallets with no open position show a friendly message instead of an empty grid, and wallets with no debt show an infinity symbol instead of an unreadable number.
What the Pool address actually is
The address behind pool.getUserAccountData(user) is not a fixed implementation contract; it is an EIP-1967 transparent proxy that the Aave DAO can upgrade. The Proxy Contract Detector resolves that same address and shows exactly which implementation your call lands on, which matters if you’re building tooling that hardcodes the Pool address rather than resolving it fresh. The collateral figures behind the health factor also don’t come from nowhere: Aave V3’s Pool prices positions through its own oracle contract, which sources most asset prices from Chainlink aggregators, the same kind of contract the Chainlink Price Feed Reader reads directly. That’s a distinct read from this one; this tool returns Aave’s own internal USD base currency figures, already computed from those oracle prices, not the raw feed.
Two of the positions this tool reports are themselves ERC-20 tokens. Aave mints aTokens to represent supplied collateral and variable-debt tokens to represent borrowed amounts, both regular ERC-20 contracts with their own balanceOf, readable with the ERC-20 Token Inspector the same way you’d inspect any other token.
Scaling six fields Aave returns in one struct
Aave V3’s Pool contract exposes getUserAccountData(address user), which returns collateral, debt, and risk parameters for a wallet in a single call. That single call already avoids multiple round trips, but the raw return values are scaled differently: collateral and debt use 8 decimals (Aave’s internal USD base currency), the health factor uses 18 decimals like a normal token amount, and the LTV and liquidation threshold are basis-point-style ratios with 4 decimals.
cel.bind(d, pool.getUserAccountData(user), { "healthFactor": string(formatUnits(d.healthFactor, 18)), "totalCollateralBase": string(formatUnits(d.totalCollateralBase, 8)), "totalDebtBase": string(formatUnits(d.totalDebtBase, 8)), "availableBorrowsBase": string(formatUnits(d.availableBorrowsBase, 8)), "currentLiquidationThreshold": string(formatUnits(d.currentLiquidationThreshold, 4)), "ltv": string(formatUnits(d.ltv, 4))})cel.bind(d, pool.getUserAccountData(user), …)calls the contract once and reuses the struct for every field, instead of six separate reads.useris a runtime context variable, declared assol_addressin the schema and supplied per request, so the same expression works for any wallet without being recompiled.- Each field is scaled with the decimals Aave actually uses for that value, not a single flat exponent, which is the detail that trips up a naive integration.
- When a wallet has no debt, Aave returns
healthFactorastype(uint256).max, which formats to an astronomically large number. The client detects values above a sane threshold and renders∞instead of a 59-digit string. - All six values are returned as strings so they fit in the same CEL map. CEL maps require their values to share a type, and
string(formatUnits(…))is the conversion path used across every field.
How to calculate a liquidation price by hand
The health factor is a ratio, not a price, so it does not tell you how far a collateral asset can drop before a position gets liquidated. You can get that number yourself from the same four fields this tool returns: total collateral base, total debt base, current liquidation threshold, and health factor. Aave V3 computes the health factor as:
health factor = (total collateral base * current liquidation threshold) / total debt baseLiquidation happens once the health factor reaches 1. Since collateral value moves in a straight line with the price of the underlying asset, you can rearrange the same formula to simulate a price drop and solve for the exact collateral price that would push the health factor down to 1.
Say the tool returns a health factor of 1.6, total collateral base of $10,000, total debt base of $5,000, and a current liquidation threshold of 80% (0.80). Check the health factor first: (10,000 * 0.80) / 5,000 = 8,000 / 5,000 = 1.6, which matches. Now say that $10,000 of collateral is entirely 5 ETH, so the tool’s numbers imply an ETH price of $2,000 (10,000 / 5). Debt and the liquidation threshold stay fixed as the price moves, so the liquidation price for ETH is:
liquidation price = total debt base / (collateral quantity * current liquidation threshold)liquidation price = 5,000 / (5 * 0.80) = 5,000 / 4 = $1,250The same answer falls out of the health factor directly: liquidation price = current price / health factor, or 2,000 / 1.6 = $1,250. Either way you calculate it, ETH would need to fall from $2,000 to $1,250, a 37.5% drop, before this position hits a health factor of 1 and becomes eligible for liquidation. That is the whole calculator: three fields from the tool, one division, and a price you can check against wherever you are watching the market. It is a static snapshot of today’s collateral and debt, not a simulation of future price paths, so rerun the tool after any deposit, borrow, repayment, or withdrawal to get a fresh liquidation price.
Wire it into a bot or dashboard
Each of the snippets below makes the same POST call to the evmquery REST API against the Aave V3 Pool on Ethereum. Swap in your own wallet address; the example wallet may or may not have an open position at the time you run it.
REST (curl)
curl -X POST https://api.evmquery.com/api/v1/query \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "chain": "evm_ethereum", "schema": { "contracts": { "pool": { "address": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, "context": { "user": "sol_address" } }, "expression": "cel.bind(d, pool.getUserAccountData(user), { \"healthFactor\": string(formatUnits(d.healthFactor, 18)), \"totalCollateralBase\": string(formatUnits(d.totalCollateralBase, 8)), \"totalDebtBase\": string(formatUnits(d.totalDebtBase, 8)), \"availableBorrowsBase\": string(formatUnits(d.availableBorrowsBase, 8)), \"currentLiquidationThreshold\": string(formatUnits(d.currentLiquidationThreshold, 4)), \"ltv\": string(formatUnits(d.ltv, 4)) })", "context": { "user": "0x1234567890123456789012345678901234567890" } }'Python
import requests
resp = requests.post( "https://api.evmquery.com/api/v1/query", headers={"x-api-key": "YOUR_API_KEY"}, json={ "chain": "evm_ethereum", "schema": { "contracts": {"pool": {"address": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"}}, "context": {"user": "sol_address"}, }, "expression": ( "cel.bind(d, pool.getUserAccountData(user), {" ' "healthFactor": string(formatUnits(d.healthFactor, 18)),' ' "totalCollateralBase": string(formatUnits(d.totalCollateralBase, 8)),' ' "totalDebtBase": string(formatUnits(d.totalDebtBase, 8)),' ' "availableBorrowsBase": string(formatUnits(d.availableBorrowsBase, 8)),' ' "currentLiquidationThreshold": string(formatUnits(d.currentLiquidationThreshold, 4)),' ' "ltv": string(formatUnits(d.ltv, 4))' " })" ), "context": {"user": "0x1234567890123456789012345678901234567890"}, }, timeout=10,)print(resp.json()["result"])TypeScript
const resp = await fetch("https://api.evmquery.com/api/v1/query", { method: "POST", headers: { "x-api-key": process.env.EVMQUERY_API_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ chain: "evm_ethereum", schema: { contracts: { pool: { address: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" }, }, context: { user: "sol_address" }, }, expression: 'cel.bind(d, pool.getUserAccountData(user), { "healthFactor": string(formatUnits(d.healthFactor, 18)), "totalCollateralBase": string(formatUnits(d.totalCollateralBase, 8)), "totalDebtBase": string(formatUnits(d.totalDebtBase, 8)), "availableBorrowsBase": string(formatUnits(d.availableBorrowsBase, 8)), "currentLiquidationThreshold": string(formatUnits(d.currentLiquidationThreshold, 4)), "ltv": string(formatUnits(d.ltv, 4)) })', context: { user: "0x1234567890123456789012345678901234567890" }, }),});const { result } = await resp.json();The free tier has no monthly cap. Get a free API key to drop these snippets into your project.
Who actually watches a health factor
- Liquidation and risk bots. Poll a watchlist of wallets and alert before a health factor crosses your own risk threshold, ahead of any liquidation.
- Borrower dashboards. Show a user their own Aave position, including collateral, debt, and how much headroom they have to borrow, without hardcoding the Pool ABI. Let the same dashboard accept an ENS name instead of a raw address by resolving it first with the ENS Resolver.
- Portfolio and treasury monitoring. Track how a DAO or fund’s Aave exposure moves as collateral prices and interest accrual change. If the wallet has granted a router or automation contract an allowance to manage its position, the Token Allowance Checker shows exactly how much that spender can move.
- Pre-transaction sanity checks. Before submitting a withdrawal or borrow transaction, confirm the resulting health factor stays in a safe range.
FAQ
What is the Aave health factor?
The health factor is a single number Aave V3 computes from a wallet’s collateral, debt, and liquidation threshold. It measures how safe a borrowing position is: the higher the number, the safer the position. It comes directly from the pool’s getUserAccountData function.
What does a health factor below 1 mean?
A health factor below 1 means the position is eligible for liquidation. Liquidators can repay part of the debt and seize collateral at a discount. A health factor between 1 and 1.5 is generally considered close to risk and worth monitoring closely.
Which chains are supported?
The checker currently runs against the Aave V3 Pool on Ethereum, Base, and Polygon. Additional EVM chains are being added on the evmquery backend as Aave V3 deploys to them.
Is this real-time?
Yes. Every read hits the latest block at request time. There is no caching layer between the tool and the chain, so the numbers reflect the current on-chain state.
Does it work with wallets that have no borrows?
Yes. When a wallet has no debt, Aave returns an effectively infinite health factor (the maximum representable integer). The tool detects that case and shows ∞ with a note that the position is not at liquidation risk, instead of a 59-digit number.
Can I use this from my own application?
Yes. The same expression and pool address work against the public REST API. The free tier has no monthly cap, and a single check counts as one read because the pool call is a single eth_call round trip. Bring your own API key and the rate limit applied to this page no longer applies.
Limits and accuracy
- The result reflects the latest block at the time of the read. There is no historical replay of health factor over time.
- Total collateral, total debt, and available borrows are denominated in Aave’s internal USD base currency, which is derived from the protocol’s own oracle prices, not a third-party price feed.
- The demo is rate limited per browser. If you hit the limit, grab a free API key and the limit goes away.
This tool reads the Aave V3 core Pool market on each chain. Isolated or permissioned Aave markets, and Aave V2 deployments, are out of scope.
Related
- Proxy Contract Detector: resolve the Aave V3 Pool’s proxy chain directly
- Chainlink Price Feed Reader: read the aggregator prices Aave’s oracle sources from
- ERC-20 Token Inspector: inspect the aToken or debt token behind a position
- Token Allowance Checker: check what a router or automation contract is approved to move
- ENS Resolver: resolve a
.ethname to the wallet address this tool needs - Monitor blockchain data from Python: extend the same pattern into a polling loop that alerts on health factor changes
- Multicall3 batching for EVM contract reads: why one expression can replace many
eth_callround trips - evmquery’s free tools: try the Aave health checker and more