Vaults

Deeper info on lending and IMFs.

Basin Vaults

Basin starts its journey towards an open and accurate financial marketplace with Basin Vaults, our minimum viable synth product. Vaults allows you to use different collateral types to mint synthetic tokens, starting with BAI.

They are built upon the Compound protocol and therefore share many similar functions and components. If you are not familiar with the Compound protocol, we recommend reading through their documentation which is extensive and well structured.

Inverse Finance expanded this protocol by introducing the Fed as an additional actor. The Fed is a smart contract (controlled by a multisig) that is able to mint ERC20 tokens and deposit them directly into the protocol.

These ERC20 tokens can now be borrowed, with collateral that has been deposited into the protocol. In order to determine how many of the ERC20 tokens users can borrow, a price needs to be established. This is done via an Oracle contract that contains a mapping from the ERC20 token to a chainlink price feed. It is a smooth way to turn compound token lending system into a system for minting synthetic tokens.

Basin USD ($BAI)

BAI allows any user access to a dollar-pegged token and to be their own bank. You can take out or repay loans in seconds, without any approvals or credit checks. BAI is backed by locked collateral tokens and there are multiple mechanisms helping it keep its peg. Its supply is controlled by "the fed". Below we will explore the various pegging mechanisms, which all work together to help BAI's USD stay as close to its peg as possible.

Ballast PSM

Ballast allows users to mint BAI with DAI or redeem deposited DAI with BAI. The mint and redeem fee is set to 1%, which means the price of BAI should fluctuate between $0.99 and $1.01. Any time the price is above or below this price represents an opportunity for low-risk arbitrage between the ballast and the market selling outside of these prices. This allows users to repay their loans at close to $1 even if the price of BAI deviates from the peg on exchanges.

Loan Arbitrage

When the price of BAI is >$1 there will be an incentive to take out a new loan position and sell it at a premium. When the price of BAI is below <$1 there is an incentive to buy BAI for a discount and pay off loans.

Supply

The supply of BAI can be contracted or expanded which will in turn increase or decrease the interest rates for borrowing or lending Basin USD. If the price of BAI is below its peg, the supply of BAI can be contracted, increasing the interest rate on all loans in the system. This will help to increase buy pressure as the incentive to pay back a loan is increased, or from people who want to take advantage of the inflated interest rate by buying BAI USD and lending it. The opposite can of course be done if the price is above peg.

Liquidations

Liquidations are vital for the safety of the protocol. To ensure that no borrow position is ever under-collateralized anyone has the ability to repay another user's borrow if the borrowed value has exceeded their borrow limit. As liquidations have to be performed in a timely manner, a share of the borrower's collateral will be transferred to the user that liquidated/repaid the borrower's position.

The Liquidation Incentive dictates what percent of the repaid amount is seized as a reward to the liquidator.

  • Liquidation Penalty: 10%

In order to increase the security of the protocol in this early stage, a percentage of the liquidation reward goes to the protocol reserves.

  • Protocol Share: 2.8%

  • Liquidator Incentive: 7.2%

IMF

The Initial Margin Factor (IMF) is independently set for each collateral asset and influences the ratio at which the value of borrowed assets has to be covered by collateral.

As an example: We have deposited USDC as collateral into the protocol. We now want to use our USDC in order to borrow BAI. If a collateral type has a default collateral factor of 0.9 it means that users can use 90% of deposited collateral to borrow BAI. For most users that knowledge will be sufficient.

For users with larger deposits (we are talking of valuations +$1,000,000) a high collateral factor such as 90% poses a higher risk to the protocol. In order to prevent volatile markets or slow liquidators causing insolvency of the protocol (and the user), we decrease the relative borrowing power with an increase in collateral value.

The IMF dictates how steep the drop in borrowing power is with an increase in collateral value.

The IMF is calculated with the following formula, where CF = Collateral Factor:

CF=SizePricemin(MaxCF,1.1/(1+IMFsqrt(size))CF= Size* Price * min(MaxCF, 1.1 / (1+IMF*sqrt(size))

The implementation in the comptroller.sol contract:

    function getHypotheticalAccountLiquidityInternal(
    address account,
    CToken cTokenModify,
    uint redeemTokens,
    uint borrowAmount)
    internal view returns (Error, uint, uint) {
    
    AccountLiquidityLocalVars memory vars; // Holds all our calculation results
    uint oErr;

    // For each asset the account is in
    CToken[] memory assets = accountAssets[account];
    for (uint i = 0; i < assets.length; i++) {
        CToken asset = assets[i];

        // Read the balances and exchange rate from the cToken
        (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);
        if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades
            return (Error.SNAPSHOT_ERROR, 0, 0);
        }
        vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});
		vars.imfFactor = Exp({mantissa: markets[address(asset)].imfFactorMantissa});
        vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});

        // Get the normalized price of the asset
        vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);
        
        if (vars.oraclePriceMantissa == 0) {
            return (Error.PRICE_ERROR, 0, 0);
        }
        
        vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});
		
	vars.precomputeTokens = mul_ScalarTruncate(vars.exchangeRate, vars.cTokenBalance);
		
	vars.postIMFSize = mul_ScalarTruncate(vars.imfFactor, sqrt(vars.precomputeTokens));
		
	vars.modCollateralFactor = mul_ScalarTruncate(vars.collateralFactor, 1e18);

	vars.preMinDenum = (1000000000000000000 + mul_(1000000000, vars.postIMFSize));

	vars.preMinEnum = 1100000000000000000;
		
	vars.preMin = div_(mul_(vars.preMinEnum, 1e18), vars.preMinDenum);

	vars.getMin = min(vars.modCollateralFactor, vars.preMin);
		
	//convertGetMin to Exp
	vars.convertedGetMin = Exp({mantissa: vars.getMin});
        
        // Pre-compute a conversion factor from tokens -> ether (normalized price value)
        vars.tokensToDenom = mul_(mul_(vars.convertedGetMin, vars.exchangeRate), vars.oraclePrice);

        // sumCollateral += tokensToDenom * cTokenBalance
        vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);
        
        // sumBorrowPlusEffects += oraclePrice * borrowBalance
        vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects);

        // Calculate effects of interacting with cTokenModify
        if (asset == cTokenModify) {
            // redeem effect
            // sumBorrowPlusEffects += tokensToDenom * redeemTokens
            vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);

            // borrow effect
            // sumBorrowPlusEffects += oraclePrice * borrowAmount
            vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);
        }
    }

    // These are safe, as the underflow condition is checked first
    if (vars.sumCollateral > vars.sumBorrowPlusEffects) {
        return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);
    } else {
        return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);
    }
}

Last updated