Search…
⌃K

# Pool Contract

In the following sections we elaborate the Pool.sol specification.

## Purpose

The Pool.sol contract handles the core logic required to implement pool-based borrowing. It handles important functions such as lending, borrowing, repayments, etc.

## Roles

#### Assignment

• by deploying the contract
• gaining ownership from previous admin

#### Permissions

• can transfer ownership to new admin
• can update the pool logic
• can update thresholds for relevant parameters

#### Note

Functions performed by the admin are meant to be transferred to governance over time.

### Borrower

#### Assignment

• by pool creation

#### Permissions

• can call functions surrounding the loan - withdrawing amount raised, repayments, responding to margin calls, etc.

### Lender

#### Assignment

• Having possession of the pool's tokens

#### Permissions

• can supply liquidity, withdraw repayments, or execute margin calls on the borrower

## Functionality

### Borrowing from a Pool

Once the collection period for a pool ends, the borrower can start withdrawing liquidity from the pool. Withdrawing the borrowed amount must be done within the withdrawal period. Having a withdrawal period ensures that the borrower cannot maliciously lock away capital from lenders by never withdrawing assets from the pool.

#### Function

function withdrawBorrowedAmount()
external override onlyBorrower(msg.sender) nonReentrant {

• None

#### Restrictions

• current time must be greater than loanStartTime and less than the loanWithdrawalDeadline
• msg.sender should be the borrower as defined through pool creation
• the total amount collected in the pool must be greater than or equal to the minimum borrow amount
• the pool's current collateral ratio must be greater than or equal to idealCollateralRatio

#### Arguments

• None - msg.sender has to be the borrower

### Supplying capital to a Pool

Lenders can deposit liquidity into a pool during the collection period. Liquidity deposited cannot be withdrawn unless one of the following conditions are met:
• the pool is terminated due to malicious activity
• the pool is cancelled by the borrower
• the borrower fails to withdraw the loan amount before the loanWithdrawalDeadline
• the borrower repays the loan at the end of the loan duration
• the pool is liquidated due to late repayments or a margin call by the lender

#### Function

function lend(
uint256 _amount,
bool _fromSavingsAccount
) external payable nonReentrant {

• None

#### Restrictions

• If the pool creator has specified a lenderVerifier then the lender must be verified by them
• the loan must be in the collection period

#### Arguments

• _lender: address of the lender. Note that the msg.sender need not be _lender
• _amount: amount the lender wishes to lend
• _fromSavingsAccount: if true, _amount from msg.sender's Sublime Savings Account is withdrawn. If false _amount is directly transferred from msg.sender's wallet address

### Liquidating a Pool

An entire pool can be liquidated in case of missed repayments. In case the normal interval deadline is missed, the borrower enters a grace period, during which it is still possible for them to repay any interests due within that period. The borrower further has the possibility of requesting for an extension of the deadline for any given instalment period. However, each pool can only receive a single extension. In case all of the above measures fail, a liquidator can liquidate the pool collateral to receive the pool's collateral and the liquidation reward.

#### Function

function liquidatePool(
bool _fromSavingsAccount,
bool _toSavingsAccount,
bool _recieveLiquidityShare
) external payable nonReentrant {

• None

#### Restrictions

• the pool must be ACTIVE
• the borrower is currently in default

#### Arguments

• _fromSavingsAccount: if true, liquidity from msg.sender's Sublime Savings Account is used to buy out the collateral. If false, msg.sender directly transfers liquidity from their wallet
• _toSavingsAccount: if true, the liquidated collateral is transferred to msg.sender's Sublime Savings Account. If false, the liquidated collateral is transferred to msg.sender's wallet
• _receiveLiquidityShare: If true, liquidated collateral is directly transferred as LP tokens. If false, liquidated collateral is first converted to base tokens before transferring to msg.sender

### Liquidating a margin call

Lenders can use margin calls to request the borrower to add additional collateral to the pool in case they fall below idealCollateralRatio. If the borrower fails to meet a margin call, a liquidator can liquidate the lender's position in the pool by transferring an amount (denominated in borrowAsset) equal to the value of the collateral backing the lender's position.

#### Function

function liquidateForLender(
bool _fromSavingsAccount,
bool _toSavingsAccount,
bool _recieveLiquidityShare
) external payable nonReentrant {

• None

#### Restrictions

• loan status must be ACTIVE
• the current time must be greater than or equal to marginCallEndTime
• idealCollateralRatio must be greater than the borrower's collateral ratio wrt the lender that executed the margin call
• _lender must be a valid lender in the pool

#### Arguments

• _lender: address of the lender whose position is being liquidated
• _fromSavingsAccount: if true, liquidity from msg.sender's Sublime Savings Account is used to buy out the collateral. If false, msg.sender directly transfers liquidity from their wallet
• _toSavingsAccount: if true, the liquidated collateral is transferred to msg.sender's Sublime Savings Account. If false, the liquidated collateral is transferred to msg.sender's wallet
• _receiveLiquidityShare: If true, liquidated collateral is directly transferred as LP tokens. If false, liquidated collateral is first converted to base tokens before transferring to msg.sender

### Withdrawing repayments from pool

As the borrower repays the loan, lenders can start withdrawing them. The amount that a given lender can withdraw depends on the number of pool tokens in their possession, and the amount of interest they've already withdrawn. Repayments are directly transferred to msg.sender's wallet address.

#### Function

function withdrawRepayment()
external isLender(msg.sender) nonReentrant {

• None

#### Restrictions

• msg.sender must possess valid pool tokens in their wallet

#### Arguments

• None: msg.sender should be a valid lender (ie, possess pool tokens)

### Adding collateral to a pool

Due to price volatilities, the borrower's collateral ratio can often drop. To prevent their collateral ratio from dropping below idealCollateralRatio, borrowers can deposit extra collateral throughout the loan duration.

#### Function

function depositCollateral(uint256 _amount, bool _transferFromSavingsAccount)
external payable override {

• None

• None

#### Arguments

• _amount: The amount of collateral msg.sender wishes to deposit
• _transferFromSavingsAccount: If true, collateral is directly transferred from msg.sender's Sublime Savings Account

### Adding collateral to a margin call

In case of individual margin calls, a borrower might be requested to deposit extra collateral. Note that the collateral only goes to cover the lender that requested the margin call. The borrower only has a set amount of time since the beginning of the margin call for the excess collateral to be added. If they fail to do so, collateral backing the lender might be liquidated.

#### Function

uint256 _amount,
bool _transferFromSavingsAccount
) external payable override nonReentrant {

• None

#### Restrictions

• loan status must be ACTIVE
• the current time must be less than or equal to the marginCallEndTime

#### Arguments

• _lender: address of the lender that has an active margin call
• _amount: amount of collateral msg.sender wishes to transfer
• _transferFromSavingsAccount: If true, collateral is directly transferred from msg.sender's Sublime Savings Account. If false, collateral is transferred from msg.sender's wallet

### Closing a pool

At the end of the loan period, a pool is closed automatically when the borrower repays the last instalment. At this point, the borrower's collateral is transferred to the borrower's wallet address.

#### Function

function closeLoan()
external payable override nonReentrant onlyRepaymentImpl {

• None

#### Restrictions

• only repayment contract can call this functino
• the current status of the loan must be ACTIVE

• None

### Withdrawing liquidity from a pool

Lenders can withdraw liquidity from a pool if it is CLOSED, CANCELLED, DEFAULTED, or TERMINATED. They receive liquidity proportional to the number of pool tokens they hold.

#### Function

function withdrawLiquidity()
external isLender(msg.sender) nonReentrant {

• None

#### Restrictions

• the pool status must match CLOSED, CANCELLED, DEFAULTED, or TERMINATED

#### Arguments

• None: msg.sender's balance is checked for the relevant pool tokens

## Flow

The following describes the typical flow while creating loan requests via pools:
• Borrower can create a pool by posting a collateral and specifying the various parameters for the pool.
• Lenders can lend borrow tokens to the pool in return for poolTokens till the pool start time
• If the total amount lent is higher than the min amount specified by borrower, then pool starts.
• If the total amount lent is lower than the min amount specified, then pool is cancelled and borrower can withdraw their collateral without any penalty and lenders can withdraw the lent amount by burning the poolTokens.
• If the pool starts, borrower can still cancel the pool within the withdrawal deadline till they withdraw the lent amount. But borrower will have to pay penalty based on the time between pool start and pool cancel times. Penalty received is distributed to the lenders in the proportion of poolTokens they hold.
• Pool can liquidated if repayments aren't correctly made or collateral ratio is not maintained above threshold.
• In case repayments not made, any one can liquidate the pool in return for a part of collateral as incentive. Liquidator has to supply borrow tokens equivalent to the collateral - (liquidator incentive) while liquidation.
• In case of collateral ratio not maintained above threshold, any lender can liquidate collateral proportional to the poolTokens they hold by making margin calls.
• Once a margin call is made, borrower has to supply enough collateral specific to the lender who made the margin call, so that borrower's collateral ratio is higher than the threshold. The collateral supplied is specific to the lender and can only be liquidated for that lender.
• If all repayments are made as per the pool parameters, the pool will be closed as soon as the principal is repaid and collateral is returned back to the borrower.

## Helpers

### PoolConstants

This function is used to query parameters which are set while creating pool and are constant
function poolConstants() returns (
uint256 borrowAmountRequested,
uint256 minborrowAmount,
uint256 loanStartTime,
uint256 idealCollateralRatio,
uint256 borrowRate,
uint256 noOfRepaymentIntervals,
uint256 repaymentInterval,
)
• borrower : Borrower requesting loan from the pool
• borrowAmountRequested : Maximum amount of borrowAsset tokens requested
• minborrowAmount : Minimum amount of borrowAsset tokens below which pool will be cancelled
• loanStartTime : Timestamp till which borrowAsset tokens can be lent and at which the loan starts
• loanWithdrawalDeadline : Timestamp till which borrower can withdraw lent tokens after loan starts
• borrowAsset : Address of token which is being borrowed
• idealCollateralRatio : Ratio of collateral to the totalDebt (principal + interest) which is to be maintained subject to a volatility threshold that can be queried from poolFactory (link here). This parameter is multiplied by
$10^{30}$
• borrowRate : Rate of interest per annum multiplied by
$10^{30}$
• noOfRepaymentIntervals : Number of intervals in which repayment has to be made
• repaymentInterval : Time in seconds per repayment interval
• collateralAsset : Address of token which is posted as collateral
• poolSavingsStrategy : Address of strategy into which collateral tokens are invested while pool is active

### PoolVars

This function is used to query the variables used to maintain the state of the Pool
function poolVars() returns (
uint256 baseLiquidityShares,
uint256 extraLiquidityShares,
LoanStatus loanStatus,
uint256 penalityLiquidityAmount
)
• RETURNS
• baseLiquidityShares : Liquidity shares received by investing the collateral in pool's strategy
• extraLiquidityShares : Liquidity shares received by investing the collateral added as part of margin calls
• loanStatus : Status of the Pool (ref)
• penalityLiquidityAmount : Amount of collateral held as penalty for cancelling the pool

### Lenders

This function is used to query the details of lender to the pool
uint256 principalWithdrawn,
uint256 interestWithdrawn,
uint256 lastVoteTime,
uint256 marginCallEndTime,
uint256 extraLiquidityShares
)
• lender : Lender of the pool
• RETURNS :
• interestWithdrawn : Interest withdrawn by the lender till now
• marginCallEndTime : End time of margin call if call is made, otherwise 0
• extraLiquidityShares : Liquidity Shares for the extra collateral received from borrower as part of margin calls

### InterestTillNow

This function is used to query the interest that is outstanding at the time of call
function interestTillNow() view returns(uint256 interest)
• interest : Interest that is outstanding till now
Note: The interest changes with every second, hence every block. So please keep in mind that interest returned by the above function is at the time of query.

### calculateCollateralRatio

This function is used to query the collateral ratio of any user, given the balance of the user and total collateral allocated to the user.
function calculateCollateralRatio(uint256 balance, uint256 liquidityShares) returns (uint256 ratio)
• balance : Pool Token balance of user to calculate collateral ratio
• liquidityShares : Liquidity shares of collateral to calculate collateral ratio
• RETURNS :
• ratio : Collateral ratio calculated

### getCurrentCollateralRatio

#### Pool

This function is used to query current collateral ratio of pool
function getCurrentCollateralRatio() returns (uint256 ratio)
• RETURNS : Collateral ratio of the pool
Note: Collateral ratio might change every block as prices of the assets might change every block. Hence note that collateral ratio returned is for the block at which query is made.

#### Lender

This function is used to query current collateral ratio of lender
function getCurrentCollateralRatio(address lender) returns (uint256 ratio)
• lender : Address of lender
• RETURNS : Collateral ratio of the pool
Note: Collateral ratio might change every block as prices of the assets might change every block. Hence note that collateral ratio returned is for the block at which query is made.

### interestPerSecond

This function is used to query interest per second for a specified principal
function interestPerSecond(uint256 principal) view returns (uint256)
• principal : Principal for which interestPerSecond is calculated
• RETURNS : Interest per second for the specified principal multiplied by
$10^{30}$

### interestPerPeriod

This function is used to query interest per instalment period for a specified principal
function interestPerPeriod(uint256 principal) view returns (uint256)
• principal : Principal for which interestPerPeriod is calculated
• RETURNS : Interest per period for the specified principal multiplied by
$10^{30}$

### calculateCurrentPeriod

This function is used to calculate the current instalment period of the pool
function calcualteCurrentPeriod() returns (uint256)
• RETURNS : Current Instalment period

### calculateRepaymentWithdrawable

This function is used to query the amount of borrow tokens that can be withdrawn as repayment
• lender : Lender to calculate repayments received for
• RETURNS : Repayment that lender can withdraw

### getMarginCallEndTime

This function is used to query the end time of the margin call for a lender
function getMarginCallEndTime(address lender) view returns (uint256)
• lender : Lender to calculate margin call end time for
• RETURNS : Timestamp at which margin call will end, if margin call is active otherwise 0

### totalSupply

This function is used to query the total amount of tokens lent to the Pool
function totalSupply() view rfunction totalSupply() public view
• RETURNS : Total number of borrow tokens lent to the pool
As borrow tokens cannot be withdrawn or lent while pool is active, this function will returns constant value while pool is active.

### getLoanStatus

This function is used to query the status of the Pool
function getLoanStatus() view returns (uint256)
• RETURNS : Status of the pool, reference to the returned values is below
 LoanStatus Value COLLECTION 0 ACTIVE 1 CLOSED 2 CANCELLED 3 DEFAULTED 4 TERMINATED 5

### getEquivalentTokens

This function is used to query equivalent tokens for an amount given source and target tokens based on their prices
• source : Address of the source token
• target : Address of the target token in which equivalent tokens are to be calculated
• amount : Amount of source tokens to calculate equivalent target tokens for
• RETURNS : Equivalent target tokens for the amount of source tokens specified
Note: Equivalent tokens might change every block as prices of the assets might change every block. Hence note that equivalent tokens returned is for the block at which query is made.

### borrower

This function is used to query borrower of the pool
RETURNS : Address of the borrower of the pool