Collateral

Collateral is security that must be deposited into a smart contract to secure the loan. Collateral can only be retrieved from the contract if the loan is repaid or liquidated.

On Lenfi, collateral can be any native Cardano asset or ADA itself. However, each pool has a determined collateral that can be used for the loans.

For example:

Loan asset
Accepted collateral

Pool 1

ADA

LENFI

Pool 2

ADA

MIN

Pool 3

LENFI

ADA

Pool 4

LENFI

MIN

Each collateral token has a protocol-defined Liquidation threshold which is factored in the Health Factor calculation. A higher liquidation threshold means more collateral must be locked in order to retrieve the loan.

Collateral tokens

These are currently accepted collateral tokens.

Token
Liquidation threshold (LT)
Initial LT

ADA

130%

150%

LENFI

200%

220%

MIN

170%

190%

WMT

200%

220%

LQ

200%

220%

WRT

200%

220%

COPI

200%

220%

DJED

200%

220%

SHEN

200%

220%

SNEK

200%

220%

IUSD

170%

190%

IAG

200%

220%

HUNT

200%

220%

FLDT

200%

220%

OPTIM

200%

220%

INDY

200%

220%

FACT

200%

220%

The liquidation threshold is used when calculating the Health Factor for already active loans. While initial LT is used when a new loan is being created.

Value calculation

Collateral value is calculated using constant product formula with 0.03% fee.

```rust
pub fn token_b_received_from_seling_token_a(
  sell_amount: Rational, // Amount of collateral assets
  token_a_amount: Int, // Amount of collateral liquidity available on DEX'es
  token_b_amount: Int, // Amount of ADA liquidity available on DEX'es
) -> Int {
  let sell_amount_int = sell_amount |> rational.truncate()

  let nominator = sell_amount_int * 997 * token_b_amount
  let denominator = token_a_amount * 1000 + 997 * sell_amount_int
  let asset_return = nominator / denominator
  asset_return
}
```

This method allows Lenfi to efficiently operate in low liquidity markets.

Health Factor

The Health Factor (HF) represents the health of the loan. A borrower can only take out a loan if the HF is greater than 1. If the health factor falls below 1, the loan can be liquidated. In the event of liquidation, the liquidator repays the borrower's loan in exchange for part or all of the collateral, depending on what is needed to compensate for the repayment.

Health Factor - new loan:

Health Factor - loan is active


Example 1: New Loan with Healthy Factor

  • Collateral Value: 200 ADA

  • Loan Amount: 100 ADA

  • Initial Collateral Ratio: 1.5

Health Factor = (200 / 100) / 1.5 = 1.33

The Health Factor is greater than 1, so the loan can be taken out safely.

Example 2: Active Loan with Risky Factor

  • Collateral Value: 200 ADA

  • Loan Amount + Interest: 155 ADA

  • Liquidation threshold: 1.3

Health Factor = (200 / 155) / 1.3 = 0.992

The Health Factor has fallen below 1, meaning the loan can be liquidated.

Below functions consumed collateralValue and loanValue calculated using price feeds.

/// Calculate health from debt, collateral, threshold
pub fn calculate_health_factor(
  debt: Int,
  collateral: Int,
  threshold: Int,
) -> Option<Rational> {
  collateral * 1000000000000
    |> rational.new(threshold * debt)
}

/// Health factor >= 100%
pub fn check_is_overcollaterized(
  value_in_debt: Int,
  collateral_value: Int,
  liquidation_threshold: Int,
) -> Bool {
  // Check if loan is overcollaterized. Meaning 'value' in debt is large enought compared to collateral factor.
  let over_collateralized: Bool =
    when
      calculate_health_factor(
        value_in_debt,
        collateral_value,
        liquidation_threshold,
      )
    is {
      Some(rat) -> Some(rational.compare(rat, 1000000 |> rational.from_int))
      None -> None
    } == Some(Greater)
  over_collateralized
}

/// Health factor < 100%
pub fn check_is_undercollaterized(
  value_in_debt: Int,
  collateral_value: Int,
  liquidation_threshold: Int,
) {
  let under_collateralized: Bool =
    (
      calculate_health_factor(
        value_in_debt,
        collateral_value,
        liquidation_threshold,
      )
        |> option.map(rational.compare(_, 1000000 |> rational.from_int))
    ) == Some(Less)
  under_collateralized
}

Last updated