Borrowing Logics

Here the logics used in Borrowing contract and BorrowLib are explained.

In code, many base PRECISION are used to avoid, arithmetic, division or modulo by zero errors.

USDa to mint

borrowing.sol
function _transferToken(
        address _borrower,
        uint256 amount,
        uint128 _ethPrice,
        uint256 optionFees
)
Param Name
Param Type
Description

_borrower

address

Address of the borrower.

amount

uint256

Deposited ETH amount.

_ethPrice

uint128

Current ETH price.

optionFees

uint256

Options fees to deduct from borrower.

uint256 tokensToLend = BorrowLib.tokensToLend(amount, _ethPrice, LTV);
bool minted = usda.mint(_borrower, (tokensToLend - optionFees));
BorrowLib.sol
function tokensToLend(
        uint256 depositedAmont, 
        uint128 ethPrice, 
        uint8 LTV
    ) public pure returns(uint256){
        uint256 tokens = (depositedAmont * ethPrice * LTV) / (USDA_PRECISION * RATIO_PRECISION);
        return tokens;
}

Calculate the USDa to lend, by using LTV ratio. Then deduct the options fees, mint the remaining to borrower and options fees to treasury.

Functions which are using the above logic

LTV is global variable in Borrowing contract.

ABOND to mint

borrowing.sol
function _mintAbondToken(
        address _toAddress, 
        uint64 _index, 
        uint256 _amount
)
Param Name
Type
Description

_toAddress

address

Address of the borrower.

_index

uint64

For which position index needs to mint ABOND.

_amount

uint256

ETH backed.

uint128 amount = BorrowLib.abondToMint(_amount,bondRatio);
BorrowLib.sol
function abondToMint(
        uint256 _amount, 
        uint64 _bondRatio
) public pure returns(uint128 amount){
        amount = (uint128(_amount) * USDA_PRECISION)/_bondRatio;
}

Calculate the ABOND to mint to user during withdraw based on bondRatio and mint it to borrower.

Functions which are using the above logic

Normalized amount calculation

borrowing.sol
uint256 normalizedAmount = BorrowLib.calculateNormAmount(tokensToLend,lastCumulativeRate);
BorrowLib.sol
function calculateNormAmount(
        uint256 amount,
        uint256 cumulativeRate
) public pure returns(uint256){
        return (amount * RATE_PRECISION)/cumulativeRate;
}

Calculate the normalized amount by dividing the total borrowed amount with cumulative rate. Cumulative rate should get from calculateCumulativeRate method.

Functions which are using the above logic

ABOND USDa Pool Calculation

borrowing.sol
uint256 discountedETH = BorrowLib.calculateDiscountedETH(
    depositDetail.depositedAmount,
    _ethPrice
    );
BorrowLib.sol
function calculateDiscountedETH(
        uint256 amount,
        uint128 ethPrice
    ) public pure returns(uint256){
        return ((((80*calculateHalfValue(amount))/100)*ethPrice)/100)/USDA_PRECISION;
}

function calculateHalfValue(uint256 amount) public pure returns(uint128){
        return uint128((amount * 50)/100);
}

Calculates the 50% of the deposited amount value with current ETH price, then 80% of the calculated amount is going to ABOND USDa pool to back ABOND.

Functions which are using the above logic

Withdraw ETH calculation

borrowing.sol
uint128 ethToReturn;
//Calculate current depositedAmount value
uint128 depositedAmountvalue = (
    depositDetail.depositedAmount * depositDetail.ethPriceAtDeposit)/_ethPrice;

if(borrowingHealth > 10000){
    // If the ethPrice is higher than deposit ethPrice,call withdrawOption in options contract
    ethToReturn = (depositedAmountvalue + (options.calculateStrikePriceGains(depositDetail.depositedAmount,depositDetail.strikePrice,_ethPrice)));
    if(ethToReturn > depositDetail.depositedAmount){
        ethRemainingInWithdraw += (ethToReturn - depositDetail.depositedAmount);
        omniChainBorrowing.ethRemainingInWithdraw += (ethToReturn - depositDetail.depositedAmount);
    }else{
        ethRemainingInWithdraw += (depositDetail.depositedAmount - ethToReturn);
        omniChainBorrowing.ethRemainingInWithdraw += (depositDetail.depositedAmount - ethToReturn);
    }
    ethValueRemainingInWithdraw += (ethRemainingInWithdraw * _ethPrice);
    omniChainBorrowing.ethValueRemainingInWithdraw += (ethRemainingInWithdraw * _ethPrice);
}else if(borrowingHealth == 10000){
    ethToReturn = depositedAmountvalue;
}else if(8000 < borrowingHealth && borrowingHealth < 10000) {
    ethToReturn = depositDetail.depositedAmount;
}else{
    revert("BorrowingHealth is Low");
}

Calculate the withdraw amount by taking the ratio of deposit ETH price to current ETH price.

If the current ETH price is higher than deposited ETH price,

Cumulative rate calculation

BorrowLib.sol
function calculateCumulativeRate(
        uint128 noOfBorrowers,
        uint256 ratePerSec,
        uint128 lastEventTime,
        uint256 lastCumulativeRate
    )
Param Name
Type
Description

noOfBorrowers

uint128

Total number of borrowers in treasury.

ratePerSec

uint256

Interest rate per second.

lastEventTime

uint128

Timestamp of last event.

lastCumulativeRate

uint256

Previous cumulative rate.

Here, event represents Deposit, Withdraw and Liquidation.

BorrowLib.sol
currentCumulativeRate = lastCumulativeRate * _rpow(ratePerSec, timeInterval, RATE_PRECISION);
currentCumulativeRate = currentCumulativeRate / RATE_PRECISION;
Current cumulative rate = last cumulative rate * (rate per second) ^ time interval.

To calculate the current cumulative rate, multiply the previous cumulative rate with interest rate per second to the power of time interval between two events.

Functions which are using the above logic

Calculation of ratio of CDS Pool value to ETH vault value

BorrowLib.sol
function calculateRatio(
        uint256 _amount,
        uint currentEthPrice,
        uint128 lastEthprice,
        uint128 noOfBorrowers,
        uint256 latestTotalCDSPool,
        IBorrowing.OmniChainBorrowingData memory previousData
)    
Param Name
Type
Description

_amount

uint256

ETH amount, the user is depositing.

currentEthPrice

uint256

Current ETH to USD price.

lastEthPrice

uint128

ETH price when the last event happened.

noOfBorrowers

uint128

Total number of borrowers in the protocol.

latestTotalCDSPool

uint256

Total CDS amount accumulated in the protocol.

previousData

Struct OmniChainBorrowingData

Previously stored global data of borrowing contract.

BorrowLib.sol
// Calculate net P/L of CDS Pool
netPLCdsPool = price difference between current and last ETH price * noOfBorrowers;
previousData.cdsPoolValue = previousData.totalCDSPool + netPLCdsPool;

Initially calculate the net P&L of CDS, if the current ETH price is higher than last ETH price , then its profit else its loss.

If the ratio calculation is for first deposit in the protocol, then calculate net CDS Pool value by adding netPLCdsPool with total CDS amount accumulated. else,

BorrowLib.sol
previousData.cdsPoolValue = previousData.cdsPoolValue + ( 
    latestTotalCDSPool - previousData.totalCDSPool) + netPLCdsPool;

Add the netPLCdsPool with previous net CDS Pool value and CDS amount deposited after last event.

BorrowLib.sol
ratio = currentCDSPoolValue / currentEthVaultValue;

Finally, calculate the ratio by dividing currentCDSPoolValue by currentEthVaultValue.

Functions which are using the above logic

Downside Calculation

BorrowLib.sol
function calculateDownsideProtected(
    uint128 amount,
    uint128 currentEthPrice,
    uint128 depositEthPrice
) public pure returns (uint128) {
    if (currentEthPrice < depositEthPrice) {
        return
            (amount * (depositEthPrice - currentEthPrice)) /
            (100 * USDA_PRECISION);
    } else {
        return 0;
    }
}

Calculates the downside needs to protect by CDS user.

Functions which are using the above logic

Options fees per second Calculation

BorrowLib.sol
function calculateOptionsFeesPerSec(
    uint128 optionsFees
) public pure returns (uint128) {
    return (optionsFees * OPTIONS_FEES_PRECISION) / 30 days;
}

Calculates the options fees per second by dividing the options fees paid by user during deposit by number of seconds in 30 days.

Last updated