Core concepts

Collateral & LTV

How loan-to-value is computed, who enforces it, and what allowedCollateral actually gates.

LTV on Lendr is a borrower decision, not a protocol parameter. The contract has no price feed and no notion of USD value anywhere in abi.ts — it only ever moves exact token amounts that were specified when the listing was created.

How the UI computes LTV

math.ts
export function tokenAmountUsd(amount: bigint, decimals: number, priceUsd: number): number {
  const asNumber = Number(amount) / 10 ** decimals;
  return asNumber * priceUsd;
}

export function ltvPct(loanUsd: number, collateralUsd: number): number | null {
  if (collateralUsd <= 0 || !Number.isFinite(loanUsd) || !Number.isFinite(collateralUsd)) return null;
  return (loanUsd / collateralUsd) * 100;
}

collateralUsd and loanUsd come from a live price lookup fetched client-side purely for display — in the Create listing modal's preview, and in the market table's LTV column. USDG is treated as pegged at 1.00 for this calculation. None of this runs on-chain, and none of it blocks a transaction; you can create or fill a listing at any LTV the two parties agree to, including one deeply above 100%.

What is enforced on-chain: allowedCollateral

The one collateral-related check the contract does make is a binary allow-list, fixed at deployment. createListing will revert for a collateralToken the market wasn't deployed with.

text
allowedCollateral(token) → bool

"Max LTV" figures are informational, not enforced

Any LTV ceiling shown in marketing copy or the UI is a guideline for the humans on either side of a listing, not a contract-level guarantee. Lenders should independently evaluate the LTV of every listing before filling it — the same way they'd evaluate APR and term.