There is a Liquidity Providers’ Pool (LPP) instance per denomination that serves all borrow requests and repayments in that same denomination. LPP calculates the total principal and interest due and keeps details of the opened loans. Each LPP instance calculates a fixed interest rate on a borrow request and a total liability amount. LPPs do not deal with currencies other than the LPP native one, LPN.
All lease positions are created by the Leaser contract, which acts as a smart contract factory. One Leaser is connected to one LPP and, therefore, to one stablecoin currency, the liquidity pool’s native currency, LPN. If a user wants to borrow USDC, they need to make a request to the Leaser contract that is connected to the LPP with USDC as an LPN.
The Leaser smart contract is configured with the following parameters:
|Code ID||The ID of the Lease smart contract is used when initializing new Lease contracts.|
|LPP address||The address of the LPP Smart Contract for the given LPN currency.|
|Lease interest rate margin||The interest rate that goes to the protocol to perform buybacks, for example, 3%.|
|Lease max liability||This will cause a liquidation, for example, 90%.|
|Lease healthy liability||The percentage threshold must be less than the Lease max liability. It will act as the desired liability when liquidation happens. For example, it may be 83%.|
|Lease initial liability||It’s the maximum possible loan-to-value (LTV) margin indicator determined at the opening of the Lease and is less than the healthy liability. For instance, it may be 60%.|
|Period length||А representation of a period in seconds. For example, 90 days = 90 days * 24 hours * 60 minutes * 60 seconds.|
|Interest due||This is the date interest is due on an open lease contract.|
|Grace period||This is the period during which a user with an open lease will be allowed not to pay the interest due. For example, 10 days = 10 days * 24 hours * 60 minutes * 60 seconds.|
|Liability reevaluation||Determines how often the invariant “liability covered” is re-evaluated. This is the period between two reevaluations, for example, every 2 seconds. What is reevaluated is whether the liability at a given time is less than the maximum allowed liability. The interest accrued for the next period is included in the market price calculation that triggers a liquidation.|
|First liquidation warning liability percentage||Used for liquidation warnings and is the first out of three. It must be less than the second liquidation warning liability percentage. For example, 83.5%.|
|Second liquidation warning liability percentage||Must be less than the second liquidation warning liability percentage. For example, 85%.|
|Third and final liquidation warning liability percentage||The third and final liquidation warning liability percentage - must be less than the max liability. For example, 87.5%.|
A mathematical representation of “liability covered”:
liability in LPN at a point of time < lease max liability * lease value in LPN Example: Loan is 150 USDC. Lease value is 250 USDC. Liability of the position is 150/250 = 0.6. Max liability is 0.9. Lease value drops to 200 USDC. Liability is 150/200 = 0.75. Lease value drops to 165 USDC. Liability is 0.91. The invariant is broken, the position is flagged for a liquidation.
Opening a new Lease is made via the Leaser by providing only the down payment. The maximum amount to be borrowed is based on the down payment and the allowed maximum initial liability percentage (e.g. 60%).
Opening a Lease Flow
1. The user opens a lease through the Leaser by providing a down payment. The options for that are as follows:
- LPN currency (e.g. stablecoin) which will be swapped via an integrated DEX (e.g. Osmosis) for the leased currency;
- Other supported currency will be swapped via an integrated DEX (e.g. Osmosis) for the leased currency;
- Same currency as the leased one, which will be added to the whole leased amount.
2. The Leaser smart contract creates a Lease instance for every opened lease. Only the Leaser is allowed to create such instances, which is verified on contract creation.
Lease stores the following data:
User → the address of the user requesting a loan;
Currency → the currency of the loan, LPN;
Current period → initially, this will be the first period, starting at the moment of loan creation and ending with the first interest due date;
- Max liability;
- Healthy liability;
- Initial liability;
- Liability reevaluation;
- Annual margin interest;
- LPP address;
- Interest due date;
- Grace period.
ℹ️ The above data points are configured in Leaser and shouldn't change during the loan lifetime, but some could be reconfigured in Leaser.
Lease calculates the maximum amount that can be borrowed based on the provided down payment and the initial liability:
borrow = initial liability * (borrow + down payment) borrow = initial liability * down payment / (1 - initial liability)
Borrow → the amount that the system will lend to the user in LPN
Initial liability → the initial liability of the lease set in Leaser's configuration, in percentage
Down payment → the provided down payment in LPN
ℹ️ The sum of the borrowed amount (loan) and the down payment equals the amount of the lease.
3. The newly created Lease requests a loan from the LPP. The LPP first verifies that the calling address is, in fact of, a Lease contract.
First, the loan's interest rate is calculated based on the LPP's current utilization and the quoted amount to open a loan:
quoted loan interest rate = base loan interest rate + (utilization factor / optimal utilization) * add-on optimal loan interest rate
Utilization shows what part of the liquidity pool is in use, meaning how much of the funds there have been borrowed, including the interest.
- The utilization factor is calculated by dividing the utilization of the pool (borrowed funds with accumulated interest) by the percentage of idle assets in the pool. For example: If the utilization rate is 60%, 40% of the assets are left unused, so the utilization factor would be:
utilization factor = utilization / idle assets portion 60% / 40% = 1.5
- The base loan interest rate is a minimum that is defined;
- The optimal utilization is the threshold that determines the cap of the quoted interest rate;
- The add-on optimal loan interest rate is a slope parameter that boosts the effect of the change in the base interest rate;
An example quoted interest rate with 60% utilization with a base interest rate of 12%, an add-on optimal loan interest rate of 2% and an optimal utilization level of 70% can be calculated the following way:
12% + (1.5/0.7)*2% = 16.29%
Afterward, the requested borrow amount is sent to the Lease address. The amount will stay there until the lease is fully repaid and closed.
The LPP stores the following data about the loan:
|Lease address||The address of the given initialized lease smart contract.|
|Principal due in LPN||The outstanding principal amount is without any accumulated interest. In the beginning, it is equal to the borrowed amount.|
|Annual interest rate||Denominated in percentage. The loan's interest does not include the margin interest that goes to the protocol to perform buybacks since the margin interest rate is configured in the Leaser smart contract.|
|Interest paid||Upon contract creation, the timestamp of that date/time is made and is dynamically updated with the timestamp of the last interest payment.|
A simplified step-by-step process for opening a lease position can be seen in the diagram below.
4. Once the loan is in the Lease contract, an Interchain Account (ICA) on a host network (e.g. Osmosis) can be opened. The Interchain Account acts as a normal account on the host chain (e.g. can stake, send, vote), however, it doesn’t require signatures using private keys for transactions, rather the actions are controlled via IBC by the owner account from the controller network - in our case, this is the Nolus chain. Opening such an account respectively requires an IBC acknowledgment (ACK) that the message is received. Should there be an issue with registering the account, a timeout is automatically triggered where the protocol waits for the next block before retrying the operation. Subsequently, a transfer out is initiated where the assets in the Lease contract (both the down payment and the loan) get transferred out via the existing established connection between the two chains. This action also needs acknowledgment in order to move to the next step which is to buy the asset of choice. When the asset is obtained, the Lease gets opened.
ℹ️ Generally, any action that involves the Nolus chain can be retried simply via a timeout, whereas for actions that are happening on a remote chain via ICA, there needs to be a step where the Interchain Account is restored, should a certain action fail to complete. In the example above, if there is a problem with purchasing a desired asset on the host network (e.g. due to relayer liveness issues) after the timeout is triggered, the Interchain Account needs to be recovered. This is because ICA channels are ordered (channel closes when a packet in the sequence times out) and not unordered like normal IBC channels.
1. The DeFi Lease position is now active. From here on there are two main actions that can take place - either repay the owed interest and principal or liquidate the position.
Should the user choose to repay, the asset which is used for repayment is compared to the LPN provided as a loan. If it is the same (assume USDC is owed and a user tries to repay again with USDC), the owed amount gets reduced immediately. If it is a different asset (e.g. ATOM), a transfer out is initiated via ICA, the asset gets swapped to the representation of the owed LPN (USDC) on the host network after which it gets transferred back to the Nolus network. After each of these actions has been acknowledged, a check is performed to see whether the loan has been repaid. If it hasn’t been, then the DeFi Lease position is still active.
An active DeFi Lease position can be liquidated as well. This can happen partially or entirely. In both cases, the asset gets swapped to the representation of the owed LPN on the host network after which that LPN gets bridged back via IBC to Nolus, respectively requiring acknowledgments for each of the actions. If the position is partially liquidated, it is still active. 2. If the position has been either fully liquidated or the owed amount (accumulated interest plus the principal) has been repaid in full by the user, then the status changes from “Opened” to “Paid”. When that happens, the user can close the position by transferring the assets in the Lease to their wallet. If this action gets acknowledged, the status of the Lease position changes to “Closed”.
2. If the position has been either fully liquidated or the owed amount (accumulated interest plus the principal) has been repaid in full by the user, then the status changes from “Opened” to “Paid”. When that happens, the user can close the position by transferring the assets in the Lease to their wallet. If this action gets acknowledged, the status of the Lease position changes to “Closed”.
The diagram below depicts a more detailed overview of each of the states of a Lease.
Query Lease Status
The status of every Lease could be queried at any time. Possible statuses are:
- Open → Lease is open, there are outstanding interest and/or principal payments to be made. At this point, liquidations could happen. The user should call Repay to make partial or full debt repayment;
- Paid → Lease is fully paid, there is no outstanding interest or principal debt, but the leased amount has not been withdrawn by the user yet and is still in the contract - Close should be executed by the user;
Returns the amount to be withdrawn by the user, respectively the leased amount
- Closed → The lease is fully paid, and the user has withdrawn the leased assets.
|Lease amount||The current balance of the Lease contract is represented by the leased assets. (Optional: this balance is equal to borrowed + down payment unless there were any liquidations)|
|Loan interest rate||The interest rate that goes to the lenders is denominated in percentage.|
|Interest rate margin||The interest rate that goes to the protocol for the buybacks is denominated in percentages.|
|Principal due in LPN||The outstanding principal amount is without any accumulated interest. In the beginning, it is equal to the borrowed amount;|
|Margin interest overdue||Outstanding margin interest for the last period if it has ended.|
|Loan interest overdue||Outstanding loan interest for the last period if it has ended.|
|Margin interest due||The outstanding margin interest up to the current moment but excluding the overdue interests from the last period.|
|Loan interest due||The outstanding loan interest up to the current moment but excluding the overdue interests from the last period.|
Quote for Loan
The user could make a query to the Leaser to get possible lease parameters based on a down payment. Note that even if the user opens a lease with the same down payment immediately after the query, the parameters could differ due to a change in the utilization of the LPP, which would affect the interest rate.
The quote returns:
- total → the total amount of the lease = down payment + borrowed
- borrowed → the amount that the system will lend to the user
- interest rate → it is comprised of the loan interest rate (paid towards the lenders) and the margin/protocol interest (used towards buybacks)
Repay and Close
The repayment covers amounts in the following order:
1. The outstanding margin interest due for the last period;
2. The LPP Loan interest is due for the last period;
3. The outstanding margin interest due for the new period, if any;
4. The LPP Loan interest is due for the new period;
5. The LPP Principal.
1. The user initiates a repayment by calling the Repay function of the Lease contract. The payment is made in LPN for the time being.
2. The Lease contract gets the current principal due and the total loan interest due of the LPP loan from the LPP smart contract:
principal due → the whole principal amount;
total loan interest due → the outstanding loan interest up until the current moment.
Two variables are also stored → change and loan payment:
change → what is left of the payment after every step of the repayment process;
loan payment → the amount that will be sent to the LPP contract at the end to cover interest and principal / repay the loan.
3. There is a defined window during which a borrower needs to pay their owed interest. A current period defining the most recent period, for which the margin interest is not yet covered, is also taken into consideration. If the leaser pays their outstanding interest, comprised of margin and loan, a new period starts. If they do not pay or fail to cover the whole amount, the period will stay the same until a new payment is made or liquidation occurs.
4. The lease determines what part of the margin interest due could be covered with payment and updates change. If payment >= margin interest due, the margin interest will be covered, otherwise only a part of it.
5. If there is enough change after the margin interest due has been paid, the Lease contract queries the outstanding loan interest.
6. Lease determines what part of the outstanding loan interest could be covered with change and updates change and loan payment. If the interest overdue for the last period has been covered, the new one starts.
7. The Lease contract calculates the margin interest due for the current period up to the present moment.
8. The lease determines what part of the margin interest due could be covered with the remaining funds, updates change, and the current period. If change >= margin interest due, the whole interest will be covered, otherwise only a part of it.
9. If the change is enough, the loan interest due is also covered. At this point, the interests are paid for both the previous and the current periods. The remaining amount, if any, is used to cover the outstanding principal.
10. If there is any amount left after the covered interests and principal, it is returned to the user. Finally, the Loan instance is deleted from the LPP storage, and the user is able to withdraw the Lease amount to their wallet.
If the borrower has open liabilities that do not meet the desired conditions set within the protocol, the system needs to sell (partially or fully) the borrower’s collateral so that it remains solvent. These conditions are defined in two invariants:
1. Interest covered
If the borrower has an outstanding margin or loan interest left after the defined interest payment period has passed, then a grace period begins during which the user has the chance to repay their owed interest. If there is no payment, the invariant is broken, and the repayment algorithm is conducted using the leased amount.
2. Liability covered
If the current liability of the position is greater than or equal to the max liability, then the invariant is broken, and a market price alarm notification message is sent. Given that the healthy liability is less than the max liability of the Lease, the liquidation amount is either the lease amount itself or the amount that is enough to guarantee a healthy position after the liquidation event has occurred. This liquidation amount is then swapped to LPN and is used as an input to the repayment algorithm. If an excess amount is returned, it is transferred to the Profit contract.
ℹ️ If the lease is fully liquidated, then it is closed.