Using Lens Contracts
This guide is for developers, analysts, and integrators who want to query protocol data efficiently and make sense of the results. We'll walk through practical examples and explain the key data types you'll encounter.
The contract ABIs and deployment addresses for lens contracts are available in the euler-interfaces repository. Be sure to use the correct address for your target network.
Connecting to a Lens Contract
To interact with a lens contract, you'll typically use a web3 library like ethers.js. All lens contracts are read-only, so you can call them from any off-chain context (scripts, dashboards, bots, etc.).
Example: Connecting to AccountLens
const { ethers } = require("ethers");
const provider = new ethers.JsonRpcProvider(RPC_URL);
const accountLens = new ethers.Contract(ACCOUNT_LENS_ADDRESS, AccountLensABI, provider);
Querying Account Data: getAccountInfo
The getAccountInfo(account, vault)
function returns a comprehensive snapshot of a user's position in a vault. The result is an AccountInfo
struct, which contains several nested types:
EVCAccountInfo
: General info about the EVC sub-account (owner, enabled controllers/collaterals, status flags)VaultAccountInfo
: Position data for the vault (balances, shares, borrowings, collateral/controller status, liquidity info)AccountRewardInfo
: On-chain reward and incentive data (balances, earned rewards, reward streams)
If you want to query the same data for all enabled collaterals and controllers of an account in one call, use getAccountEnabledVaultsInfo(evc, account)
. This function returns arrays of the same types for every enabled vault, making it efficient to fetch a user's full protocol exposure. Note that this function only returns data for vaults that are explicitly enabled as collateral or controller in the EVC - it won't return information about deposits in vaults that aren't enabled as collateral.
Example:
const account = "0x...";
const vault = "0x...";
const info = await accountLens.getAccountInfo(account, vault);
// Accessing nested data:
console.log("Owner:", info.evcAccountInfo.owner);
console.log("Vault shares:", info.vaultAccountInfo.shares);
console.log("Borrowed:", info.vaultAccountInfo.borrowed);
console.log("Is Controller:", info.vaultAccountInfo.isController);
console.log("Earned rewards:", info.accountRewardInfo.enabledRewardsInfo);
Understanding the Types
AccountInfo
: The top-level struct, grouping all relevant data for a user/vault pair.EVCAccountInfo
: Includes the EVC address, owner, enabled controllers/collaterals, and status flags (e.g., lockdown mode).VaultAccountInfo
: Contains balances, shares, borrowings, allowances, collateral/controller status, and liquidity info (including time to liquidation and collateral values).AccountRewardInfo
: Shows reward balances and details for any enabled reward streams.
Tip: Many fields are nested structs or arrays. Use dot notation to access them (e.g.,
info.vaultAccountInfo.liquidityInfo.timeToLiquidation
).
Position Health, Collateral Value, and Health Score
When analyzing your account's risk and health, it's important to understand how the protocol evaluates your positions. Here are some key concepts and how to extract them using the lens contracts:
-
Health Score (Health Rate):
-
The health score is a measure of how safe your borrow position is. It is calculated as:
healthScore = collateralValueLiquidation / liabilityValue
where both values are found in
VaultAccountInfo.liquidityInfo
. -
To get the health score for a borrow position, you must query the vault from which you borrowed (the controller vault). In the context of
getAccountEnabledVaultsInfo
, this will be the vault whereisController
is true.
-
-
Risk-Adjusted Collateral Value:
- The protocol uses different collateral values for borrowing and for liquidation:
collateralValueBorrowing
: The value of your enabled collaterals as seen for borrowing purposes.collateralValueLiquidation
: The value of your enabled collaterals as seen for liquidation purposes (usually more conservative).
- Both are available in
VaultAccountInfo.liquidityInfo
. - These values are aggregated across all enabled collaterals for the position, but you can also see the breakdown per collateral in the
collateralLiquidityBorrowingInfo
andcollateralLiquidityLiquidationInfo
arrays.
- The protocol uses different collateral values for borrowing and for liquidation:
-
Collateral Market Value (Raw):
- The raw market value of your collaterals, as seen by the controller vault, is given by
collateralValueRaw
inVaultAccountInfo.liquidityInfo
. - The breakdown per collateral is available in the
collateralLiquidityRawInfo
array.
- The raw market value of your collaterals, as seen by the controller vault, is given by
-
Off-Chain Collateral Market Value:
-
If you want to compute the market value of your collateral using off-chain prices, multiply your collateral asset balance (not shares) by the current market price of the asset. For example:
offChainCollateralValue = assetsAccount * assetPrice
where
assetsAccount
is the asset balance fromVaultAccountInfo.assetsAccount
andassetPrice
is the off-chain price per unit of the asset. -
Note: For some assets, you may need to use your own price source if the endpoint does not return a value.
-
Tip: The
getAccountEnabledVaultsInfo
function returns anAccountMultipleVaultsInfo
struct, which contains an array ofVaultAccountInfo
for each enabled collateral and controller. For borrow positions, focus on the vault whereisController
is true to get the health and risk data for your position.
Querying Vault Data: getVaultInfoFull
The getVaultInfoFull(vault)
function (from VaultLens
) returns a VaultInfoFull
struct, which is a detailed snapshot of a vault's configuration and state.
Example:
const vaultLens = new ethers.Contract(VAULT_LENS_ADDRESS, VaultLensABI, provider);
const vaultInfo = await vaultLens.getVaultInfoFull(vault);
console.log("Vault name:", vaultInfo.vaultName);
console.log("Total assets:", vaultInfo.totalAssets);
console.log("Interest rate model:", vaultInfo.interestRateModel);
console.log("Supply cap:", vaultInfo.supplyCap);
console.log("Recognized collaterals:", vaultInfo.collateralLTVInfo);
Key Types in VaultInfoFull
VaultInfoFull
: The main struct, with fields for vault configuration, totals, caps, fees, IRM, oracles, hooks, and more.LTVInfo[]
: An array of collateral types and their LTV (Loan-to-Value) parameters. EachLTVInfo
includes the collateral address, borrow and liquidation LTVs, and ramping info.VaultInterestRateModelInfo
: Details about the vault's interest rate model, including type and parameters.AssetPriceInfo
: Price and oracle data for assets and collaterals.
Tip: Arrays like
collateralLTVInfo
are append-only, so not all entries may be active collaterals. Always check the LTV values - a collateral with zeroborrowLTV
is no longer accepted as collateral. Only iterate through entries with non-zero LTVs to display currently supported collaterals and their risk parameters.
Tip:
If a vault is ramping down its liquidation LTV, you can calculate the current liquidation LTV for a collateral using the following formula, based on the fields in theLTVInfo
struct returned by the lens:// LTVInfo fields:
// - liquidationLTV: target value (uint256)
// - initialLiquidationLTV: starting value at ramp start (uint256)
// - targetTimestamp: when ramping ends (uint256, unix time)
// - rampDuration: total ramp duration (uint256, seconds)
function getCurrentLiquidationLTV(ltvInfo) {
const now = Math.floor(Date.now() / 1000); // current unix timestamp
if (
now >= ltvInfo.targetTimestamp ||
ltvInfo.liquidationLTV >= ltvInfo.initialLiquidationLTV
) {
return ltvInfo.liquidationLTV;
}
const timeRemaining = ltvInfo.targetTimestamp - now;
return (
ltvInfo.liquidationLTV +
((ltvInfo.initialLiquidationLTV - ltvInfo.liquidationLTV) * timeRemaining) /
ltvInfo.rampDuration
);
}This matches the on-chain logic: the liquidation LTV linearly ramps from
initialLiquidationLTV
toliquidationLTV
over the period ending attargetTimestamp
. If ramping is not active, just useliquidationLTV
.
Querying APYs for a Vault
To quickly fetch the current borrow and supply APYs for a vault, use the getAPYs(vault)
function from the UtilsLens
contract. This function returns the annualized borrow and supply rates, computed based on the vault's current interest rate model and utilization.
Example:
const utilsLens = new ethers.Contract(UTILS_LENS_ADDRESS, UtilsLensABI, provider);
const [borrowAPY, supplyAPY] = await utilsLens.getAPYs(vault);
console.log("Borrow APY:", borrowAPY);
console.log("Supply APY:", supplyAPY);
The returned values are typically expressed in ray units (1e27
), so you may need to convert them to a human-readable percentage (e.g., Number(borrowAPY) / 1e25
gives the APY as a percent with two decimals).
Note: The APYs returned here only include the Euler rates from lending and borrowing activity within the protocol. They do not include any intrinsic APY from the underlying asset (for example, the staking yield of wstETH) or any additional rewards. To account for those, you must supplement with external data sources.
Where to Find Type Definitions and More Resources
The full definitions of all structs and types used by lens contracts can be found in the LensTypes.sol file in the EVK Periphery repository.