There is a Liquidity Providers’ Pool (LPP) instance per denomination (LPN, i.e., native currency of an LPP), serving all lenders that provide liquidity in that same currency. Upon deposits, lenders obtain an amount of CW20 interest-bearing token or nLPN. Interest amounts are computed via index-based interest accrual.
Each nLPN represents a fraction of the deposited amount relative to the total amount of the pool. The interest accrued and paid by the borrowers enters the pool and increases the nLPN price. Once a lender withdraws nLPN, the received amount includes the interest accrued for providing the loan to the borrowers
Deposit LPN and Mint nLPN
If a user wants to become a lender in an LPP, they need to have some LPN in their wallet, for example, USDC. This amount is transferred with an input message and handled by the bank module of the Cosmos SDK
Since lenders are depositing to a pool, they need a receipt token back. It guarantees a share of the pool and can be used to withdraw the underlying assets. The balance of this receipt token is introduced to the state of the LPP smart contract initialized at 0 alongside an additional parameter describing its initial price. The price of the underlying LPN tokens is also specified as another parameter. If the balance of the nLPN tokens is empty, then the price of a single nLPN token would be equal to the initial derivative price (1 nLPN = 1 LPN). Otherwise, one needs to take into account the newly deposited LPN tokens and the loan interest rate from the borrowers. As time passes, the nLPN to LPN ratio will increase, which means one nLPN token would increase its price relative to a single LPN token. The lender's balance can always be calculated by:
lender's balance in LPN = lender's owed nLPN * price per nLPN
The amount of owed nLPN tokens by the lender is extracted from the record with the lender’s wallet address as a key that has been provided with the deposit transaction
Withdraw LPN (Burn nLPN)
To withdraw LPN tokens, the wallet address needs to have a positive amount of nLPN tokens. The request can be called multiple times, and the amount can be withdrawn in tranches
Initially, the price of the provided nLPN in LPN is computed to determine how much the lender can withdraw:
withdraw amount in LPN = provided nLPN * price per nLPN
Afterward, the balance of the nLPN in the LPP smart contract is decreased accordingly alongside the balance of the LPN tokens. Should the user wish to withdraw everything, then the rewards will be claimed and the user will not be a lender anymore. If the user wishes to withdraw only 50% of their deposited amount, then their nLPN token holdings would decrease by 50%.
Rewards
Each LPP instance regularly receives rewards from the Treasury smart contract based on LPP instance’s total value locked (TVL), the cumulative TVLs of all other LPP instances and cumulative TVL thresholds defined via governance in the Treasury contract itself. The LPP keeps track of incoming and outgoing rewards, as well as minting and burning lenders’ CW-20 tokens by maintaining a global amount of rewards in uNLS per nLPN. Each new reward increases the global reward per nLPN. When a lender deposits or withdraws/burns nLPN, rewards accrued by that lender for the balance so far is calculated based on the value of the global reward per nLPN. That amount is added to the pending rewards balance of uNLS for that user
ℹ️ The rewards per nLPN in uNLS are part of the global deposits’ state managed by the LPP smart contract, whereas the uNLS balance is kept by the bank module
ℹ️ Lender is an instance per lender containing the lender’s address, their deposited nLPN, the rewards per nLPN denominated in uNLS, and any pending rewards in uNLS
Distribute Rewards
The global reward per nLPN in uNLS increases each time the Treasury transfers uNLS tokens to the LPP
Update and Claim Rewards
The Lender’s nLPN balance changes on deposits and withdrawals. An algorithm calculates the accrued rewards of the previous balance and updates the lender’s data. In general, it keeps track of a global reward per nLPN token denominated in uNLS which increases as time passes. The lender also has a reward per nLPN token. The difference between this reward and the global one updates the pending amount. This update is triggered by either depositing/withdrawing or claiming.
Whenever the user claims, a transfer is initiated to the recipient which by default is the lender’s address but could be another if specified. The lender’s reward per nLPN is now equal to the global reward per nLPN. Should a Lender withdraw all his LPN from the LPP the rewards will be claimed and they will have no nLPN tokens
Treasury
This single instance smart contract first calculates rewards in uNLS depending on the TVL of all LPPs. These rewards are then distributed to each LPP. The TVL denomination, which is a data point used for TVL measurement, is obtained from the LPP smart contract. The APR depends strictly on TVL thresholds defined as intervals. It starts from a predefined minimum TVL and updates on the next threshold attainment. The duration is measured in hours