On-chain Components

1. Collateral Management Logic
2. Lending Pool (Issuance & Redemption logic)
3. Position Registry
4. Price Oracle
5. Audit (Update Validation Logic)

Written in Aiken and developed for TrustLevel

Building

aiken build

# Or include traces for testing/debugging:
# (Note that collateral and lending_pool contracts individually exceed tx size limit if compiled verbose)
aiken build -t verbose

Testing

To run all tests:

aiken check

To run only tests matching the string foo, do:

aiken check -m foo

Concurrency and Double-Satisfaction

To address the risk of double-satisfaction exploits, the loanable asset in the lending pool is contained in only 1 utxo.

As a consequence, only 1 transaction at a time can ever spend the lending pool’s utxo and trigger its validation rules to be evaluated.

To allow users to concurrently take loans and repay active ones, the “loan” and “repayment” interactions are broken up into 2 blockchain transactions. This is similar to the request-and-batching done by dexes.

In the first part, the user submits their request - either loan takeout or loan repayment. In this transaction, they will only be spending their own collateral utxo, so other users are not affected.

The second part, which is the fulfillment of the user’s request, is done in the backend. This is where we immediately chain the transaction that spends the lending pool’s only utxo, to send to the user the loaned asset they requested. The lending pool’s new utxo can then be persistently stored, immediately ready to be used for the next fulfillment tx without waiting on the network for finality.

Input/Redeemer Indexing

The redeemer indexing design pattern is also implemented in the protocol, to reduce double-satisfaction risks, and more importantly to significantly reduce contract execution costs.

Process

  1. Initialization

    1. Protocol owner deploys the compiled Plutus validators into utxo’s as reference scripts, and initialize the UTXOs containing the protocol’s settings.

    2. Protocol owner deposits the loanable asset into the lending_pool contract address.

  2. Usage

    • User:

      1. User deposits their collateral asset into the collateral manager contract address.

      2. User may withdraw their deposited collateral if it is not locked in an active loan.

      3. User takes out a loan by:

        • Tx 1 (by user) User submits a loan request tx. This locks their collateral deposit and records the amount they want to borrow.

        • Tx 2 (chained to Tx 1 in the backend) A tx fulfilling the loan request of the user is automatically chained to the user’s loan request. This spends the corresponding amount of loanable asset from the lending_pool contract and sends it to the requesting user.

      4. User repays an active loan through the same request-fulfill mechanism.

    • Oracle Data Provider:

      1. Trusted oracle data provider runs a service that periodically checks relevant dexes for the current price of the collateral asset against the loanable asset. The oracle price UTXO is then updated with the latest price data.
    • Admin:

      1. Admin (or anyone) runs a service that periodically checks all open loan positions for under-collateralization or maturity. If any are found, liquidation txs will be submitted for those positions.

Protocol Spec / Validator Operation

UTXOs

The current design of this protocol involves 7 validators that hold the following UTXOs respectively.

  1. refscripts.ak:

    UTXOs containing the protocol’s compiled validator code as reference scripts.

  2. settings.ak:

    UTXOs containing settings that are used by different components of the protocol.

  3. collateral.ak:

    UTXOs containing users’ collateral assets, and a reference to their loan metadata if they have an open loan position.

  4. position_registry.ak:

    UTXOs containing metadata of open loan positions (position UTXOs).

  5. lending_pool.ak:

    The single UTXO containing the loanable asset. The datum in this UTXO also contains the lending pool settings such as the collateral asset, its price, loan-to-value ratio, and the list of interest rates for different loan terms.

  6. oracle.ak:

    1. UTXO’s containing updated pricing data for the collateral asset (price UTXOs). This is used in the loan issuance logic.

    2. A single UTXO containing the oracle settings (settings UTXO) - the list of trusted providers.

  7. audit.ak:

    UTXO containing the protocol’s updated “health score” based on a number of key factors.

Position Tokens

The metadata of each open loan position are contained in UTXOs held at the position_registry contract (“position UTXO”). These position UTXOs are created when a user borrows from the lending pool, and are removed when a loan position is closed.

When a loan position is opened, a unique pair of “position tokens” are minted. These are beacon tokens used to tag the collateral UTXO that is used for the loan, and its corresponding position UTXO held at the position_registry contract. The “position tokens” link them together. Uniqueness of the pair is ensured by using the UTXO id of the input collateral UTXO.

When a loan is closed (repaid or liquidated), the position tokens are burned.

The minting policy of these “position tokens” is contained in the lending_pool contract.

Oracle Tokens

The oracle contract mints oracle price tokens: OPRC. These are beacon tokens that are used to identify the UTXO(s) containing official price data for collateral assets.

Settings Tokens

The settings contract mints 2 beacon tokens once (on initialization only):

  1. GCFG - The beacon token for the UTXO containing the global settings datum
  2. OCFG - The beacon token for the UTXO containing the oracle settings datum

Requirements when withdrawing collateral

Redeemer: WithdrawCollateral

Enforced by collateral.ak:

  1. ✅ The collateral UTXO must not be used in an open loan position.
  2. ✅ The owner of the collateral must sign the transaction.

Requirements when issuing loans

Requirements when repaying a loan

Requirements when liquidating a loan position

Requirements for minting/burning oracle beacon tokens

Redeemer: MintOracleBeacon | BurnOracleToken

Enforced by oracle.ak:

  1. ✅ The global settings UTXO must be included in the reference inputs.
  2. ✅ The global settings UTXO must contain the global settings beacon token.
  3. ✅ The admin specified in the input global settings UTXO must sign the tx.

Requirements when updating oracle price data

Redeemer: UpdateOraclePrice

Enforced by oracle.ak:

  1. ✅ The oracle price UTXO must be one of the inputs
  2. ✅ The oracle settings UTXO must be included in the reference inputs
  3. ✅ The oracle price UTXO must be returned with its updated datum still having the same structure.
  4. ✅ The tx must be signed by one of the authorized updaters.

Requirements when updating audit datum

Redeemer: UpdateAuditDatum

Enforced by audit.ak:

  1. ✅ The current audit UTXO containing the audit beacon token must be spent in the tx.
  2. ✅ The following UTXOs must be included in the reference inputs:
    1. ✅ the global settings UTXO
    2. ✅ the oracle settings UTXO
    3. ✅ the lending_pool UTXO
    4. ✅ the oracle price UTXO
  3. ✅ The output audit UTXO must be returned to the audit contract
  4. ✅ The output audit datum must have the expected structure and contents
  5. ✅ The tx must be signed by one of the trusted oracle providers

Requirements when updating global settings

Redeemer: UpdateGlobalCfg

Enforced by settings.ak:

  1. ✅ The global settings UTXO must be spent in the tx.
  2. ✅ The global settings UTXO must contain the global settings beacon token.
  3. ✅ The global settings beacon token must be returned to the settings contract.
  4. ✅ The admin specified in the input global settings UTXO must sign the tx.

Requirements when updating oracle settings

Redeemer: UpdateOracleCfg

Enforced by settings.ak:

  1. ✅ The oracle settings UTXO must be spent in the tx.
  2. ✅ The oracle settings UTXO must contain the oracle settings beacon token.
  3. ✅ The global settings UTXO must be included in the reference inputs.
  4. ✅ The global settings UTXO must contain the global settings beacon token.
  5. ✅ The oracle settings beacon token must be returned to the settings contract.
  6. ✅ The oracle settings datum structure must be preserved.
  7. ✅ The admin specified in the global settings UTXO datum must sign the tx.

Requirements when minting/burning position tokens

References Used

Search Document