We are building the product and its validators with a singular focus on creating a Permissionless system. This system is designed to be balanced, governed by smart contracts known as validators. It is an open system, free from dependencies on specific systems or individuals.
- NFT: A unique, non-fungible token whose uniqueness is guaranteed by a consumed UTXO reference.
- Pool: A UTXO with a Pool NFT, accompanied by a deposit and details (datum) locked in a
pool.ak
validator. - Oracle: A UTXO with an Oracle NFT and details (datum) locked in a
collateral.ak
validator. - Liquidity Provider (LP) Token: Fungible tokens that represent a share of the pool deposit.
- Collateral: Assets used as security to cover the value of loans taken from the pool.
- Interest Rate: Annual Percentage Rate (APR) charged on the loan amount.
- Loan: An agreement to borrow assets from a pool, governed by specific interest rates and collateral requirements.
- Pool Manager NFT: An NFT minted at the time of pool creation that allows for control over the stake address attached to
collateral.ak
andpool.ak
.
These are validation done off-chain, before pool appears on the client side. Failing to match any of below criteria would result in pool being dismissed as 'valid' and not displayed on the UI.
Pool validation
- Pool NFT is sent to
pool.ak
and Stake Credentials are correct (pool_stake.ak
script credentials) - Pool NFT policyId matches
pool.ak
- Minted LP tokens policyId matches
liquidity_token.ak
policy. Also, it is recorded in pool datum lpToken polilcyId and asset name - Pool config NFT is minted (policyId matches
pool_config.ak
) and is sent to pool Config validator pool_stake.ak
script is locked toleftovers.ak
for future contract references. With datum coressponding to Pool NFT.
Pool datum validation
collateralAddress
: validator ScriptCredential matchescollateral.ak
; Stake ScriptCredential matches pool stake credentials;LoanCs
,CollateralCs
are from approved list of borrowable and collateral assetsOracleCollateralNft/OracleLoanNft
is from approved list of oracle NFTslpToken
token name matches pool token namepoolNftName
matches pool NFT minted on the transactionPoolConfigAssetname
matches pool NFT namebalance
match pool deposit amount and is used to calculate total_lp_tokens. Cannot be 0.lent_out
= 0total_lp_tokens
match amount of LP tokens minted in the transaction
Oracle validation
- Oracle NFT is sent to oracle contract. Both match
oracle_validator.ak
Oracle datum validation poolNftCs
- hand checked valid DEX pool NFT associated to the token and ADAoracleNftCs
- minted NFT CStokenACs
- matches DEX relationtokenBCs
- is ADA ("","")tokenAAmount
- current or approximate tokenA amount in a DEXtokenBAmount
- current or approximate ADA amount in a DEXexpirationTime
- epoch time no later than 20 minutes from nowmaturityTime
- epoch time no later than 20 minutes from now
Pool Config validation
- Pool Config NFT is sent to
pool_config.ak
Config datum validation All the values are vetted by Lenfi team. liquidation_threshold
- is positive and ranging between 1,000,000 - 3,000,000. Cannot be changedinitial_collateral_ratio
- Is higher thanliquidation_threshold
. Cannot be changedpool_fee
- is not negative.loan_fee_details.tier_1_fee
- is not negativeloan_fee_details.tier_1_threshold
- is not negativeloan_fee_details.tier_2_fee
- higher thantier_1_fee
loan_fee_details.tier_2_threshold
- higher thantier_1_threshold
loan_fee_details.tier_3_fee
- higher thantier_2_fee
loan_fee_details.tier_3_threshold
- higher thantier_2_threshold
liquidation_fee
- Is not negativeplatform_fee_collector_address
- is valid addressmin_transition
- is not negativemin_loan
- is not negative
Reference Token validation
Reference token is minted at a time of protocol creation. Stores script hashes in a lock-forever script, replaces some script params and avoids circular imports thruought the protocol usage.
Offchain validates that Reference Token is and NFT locked in 'always fail' script with correct Datum values. delegator_nft_policy
- Correct pool manager NFT policyId (placeholder_nft.ak
with param of 3
) liquidations_pkh
- Correct liquidations script hash (leftovers.ak
) pool_script_hash
- Correct pool script hash (pool.ak
) pool_config_script_hash
- Correct pool config script hash (pool_config.ak
) merge_script_hash
- Correct delayed merge script hash (delayed_merge.ak
)
Unique governance NFT is minted that has an access to control every pool config (stored in poolConfigValidator). NFT will be held by developer team before it is moved to DAO validator (see pool_config.ak
for more details). Governance NFT holder will have a right to change any Pool Config Datum
except liquidation_threshold
and initial_collateral_ratio
.
collateral.ak
: Ensures fair loan issuance and repayment from the pool.pool.ak
: Manages the proper utilization of user funds.liquidity_token.ak
: Oversees fair deposits and withdrawals from the pool.pool_config.ak
: Manages pool-specific parameters which can be adjusted based on off-chain consensus.pool_stake.ak
: Ensures that delegated ADA is withdrawn to the pool. Allows to control stake address.order_contract.ak
: Executes user orders fairly when direct execution with the pool is not possible.oracle_validator.ak
: Streams token prices to the protocol.leftovers.ak
: Manages the return of any remaining collateral after loan repayment or liquidation.delayed_repayment_merge.ak
: Allows to repay/liquidate the loan by sending funds to intermediate contract. This is handy when pool is busy.placeholder_nft.ak
: Ensures that minted NFTs are unique.
- Each pool only accepts one collateral asset defined in the pool datum
- LP token holders are entitled to a proportional share of the pool balance.
- An LP token's value in relation to the pool balance can never decrease; it can only appreciate due to accrued interest.
- Borrower NFT guarantees the right to reclaim 100% of collateral if the loan is repaid.
- Borrower NFT also guarantees the right to any remaining collateral, after loan and fees, if liquidation occurs.
- Loans must be overcollateralized.
- Loans can only be liquidated if undercollateralized at the time of liquidation.
- Liquidators are allowed to claim a percentage of the collateral as a fee during liquidation.
- Liquidateion fee is set in
pool_config.ak
as a % of total collateral - All loans must eventually be repaid; failure to do so will result in the loan becoming undercollateralized due to increasing interest.
- Delegation rewards can only be withdrawn to the pool.
- Pool Manager NFT allows delegation to any Stake Pool (SPO).
- Pool configuration (
pool_config.ak
) values can be adjusted. - Oracles are used to determine asset values during borrow, liquidate, and withdraw actions.
- Oracle data must be updated based on values from a Decentralized Exchange (DEX) and is considered expired if older than 30 minutes.
- Oracle data cannot be updated more frequently than every 10 minutes.
- A pool fee, set in
pool_config
, is payable to the pool. - Utilization rate (
lent_out / (balance + lent_out)
) determines the platform fee payable to theplatform_fee_collector_address
. - The pool datum must always accurately reflect the total supply of LP tokens n=n.
- Each pool must have unique: Pool NFT, pool address, stake address, and collateral address.
- The same stake address must be enforced for both the pool and the collateral.
- A pool can be destroyed if all balance is withdrawn and the Pool Manager NFT is burned.
- When user creates a batch order, they strictly define value they want to receive.
- Anyone can execute a batch order created by user.
- Create a pool
- Delegate to an SPO
- Destroy a pool
- Deposit to a pool (may use
order_contract.ak
) - Withdraw from a pool (may use
order_contract.ak
) - Borrow (may use
order_contract.ak
) - Repay (may use
order_contract.ak
) - Liquidate (may use
order_contract.ak
) - Create an oracle
- Update oracle prices
- Creates a pool.
- Deposits funds into the pool and mints LP tokens.
- Withdraws 50% from the pool and burns the corresponding LP tokens.
- Withdraws the remaining 50% and destroys the pool.
- Borrows from the pool, locks collateral, and mints a Borrower NFT.
- Repays the loan, unlocks the collateral, and burns the Borrower NFT.
- Liquidates an undercollateralized loan by repaying the loan on behalf of the borrower.
- Locks the remaining collateral for the borrower to claim later.
- A unique Pool NFT must be minted and locked in
pool.ak
. - A unique Pool Manager NFT and Pool Config NFT must be minted.
- An initial deposit must be made to the pool.
- LP tokens must be minted to represent the initial deposit.
- LP token asset names must match the asset name of the Pool NFT.
- The
balance
andtotal_lp_tokens
fields in the pool datum must be correctly initialized.
- LP tokens must be minted to represent the deposit.
- The asset name of the LP tokens must match the asset name of the Pool NFT into which the deposit is made.
- The
balance
field in the pool datum must be incremented by the deposit amount. - The
total_lp_tokens
field in the pool datum must be incremented by the amount of minted LP tokens.
- The corresponding amount of LP tokens must be burned to represent the withdrawal.
- The asset name of the LP tokens must match the asset name of the Pool NFT from which the withdrawal is made.
- The asset name of the LP tokens must match the asset name of the Pool NFT into which the deposit is made.
- The
balance
field in the pool datum must be decremented by the withdrawal amount. - The
total_lp_tokens
field in the pool datum must be decremented by the amount of burned LP tokens.
- Mint a Borrower NFT upon initiating a loan.
- The loan amount should be smaller than the value of the collateral plus a buffer, defined as the liquidation threshold.
- Determine the interest rate as an Annual Percentage Rate (APR) for the entire loan duration.
- Securely lock collateral, which can either be claimed by the borrower upon repayment or liquidated if the loan becomes undercollateralized.
- Subject borrowers to a Loan-to-Value (LTV) ratio, as stipulated in the pool's
pool_config.ak
. - Specify the loan duration at the time of borrowing.
- Invoke
oracle_validator.ak
to determine the current value of both the collateral and the borrowed asset. - Use
leftovers.ak
to ensure that any remaining collateral is returned to the borrower once the loan is repaid or liquidated. - Decrease the
balance
and incrementlent_out
fields in the pool's datum.
- Only the holder of the Borrower NFT is authorized to repay the loan.
- Calculate the interest based on the duration the loan was active.
- Both the loan amount and interest should be repaid to the pool.
- Update the pool datum: increment the
balance
and decrement thelent_out
fields. - Grant the borrower rights to reclaim 100% of the initially locked collateral.
- Allow liquidation only when a loan is undercollateralized.
- Repay the loan and interest to the pool.
- Entitle the liquidator to a percentage of the collateral, where the percentage is specified in
pool_config
(denominated by 1,000,000, e.g., 2% = 20,000). - Make the remaining collateral claimable by the holder of the Borrower NFT.
- Enable the Pool Manager NFT holder to delegate
pool.ak
andcollateral.ak
stake addresses to any Stake Pool Operator (SPO). - Allow delegation rewards to be withdrawn only to the pool.
- Convert non-ADA assets to ADA at a fair market price (utilize the oracle) upon withdrawal.
- Update the Oracle UTXO strictly based on values from a Decentralized Exchange (DEX) UTXO.
- Restrict updates to a minimum interval of 10 minutes.
- Updated value is an average of datum from unlocked oracle UTXO and DEX