Bao Markets
BAO Markets are available for public testing, find more info in our guides​
Bao starts its journey towards an open and accurate financial marketplace with BAO Markets, our minimum viable synth product. You will be able to use different collateral types to borrow synthetic dollar pegged token Bao USD
Bao Markets are build 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 compounds token lending system into a system for minting synthetic tokens.

Bao USD

bUSD allows any users access to a dollar pegged tokens and to be their own bank. You can take out or repay loans in seconds, without any approvals or credit checks.
bUSD 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 Bao USD stay as close to its peg as possible.

Ballast

Ballast allows users to mint bUSD with DAI or redeem deposited DAI with bUSD. The mint and redeem fee is set to 1%, which means the price of bUSD 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 bUSD deviates from the peg on exchanges.

Loan Arbitrage

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

Supply

The supply of bUSD can be contracted or expanded which will in turn increase or decrease the interest rate for loans.
If the price of bUSD is below its peg the supply of bUSD 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. The opposite can of course be done if the price is above peg.
​

IMF

The Initial Margin Factor (IMF) is independently set for each bdAsset and influences the ratio at which the value of borrowed assets have 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 bUSD. If a collateral type has a default collateral factor of 0.9 it means that users can use 90% of deposited collateral to borrow bUSD. 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% pose 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.
An arbitrary example of how the IMF influences the borrowing power in comparison to a static collateral factor of 85%.
The IMF is calculated with the following formula:
CollateralFactor=sizeβˆ—priceβˆ—min(MaxCollateralFactor,1.1/(1+IMFβˆ—size)Collateral Factor = size * price * min(MaxCollateralFactor, 1.1 / (1+IMF * \sqrt{size})
The implementation in the comptroller.sol contract:
1
function getHypotheticalAccountLiquidityInternal(
2
address account,
3
CToken cTokenModify,
4
uint redeemTokens,
5
uint borrowAmount)
6
internal view returns (Error, uint, uint) {
7
8
AccountLiquidityLocalVars memory vars; // Holds all our calculation results
9
uint oErr;
10
​
11
// For each asset the account is in
12
CToken[] memory assets = accountAssets[account];
13
for (uint i = 0; i < assets.length; i++) {
14
CToken asset = assets[i];
15
​
16
// Read the balances and exchange rate from the cToken
17
(oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account);
18
if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades
19
return (Error.SNAPSHOT_ERROR, 0, 0);
20
}
21
vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa});
22
vars.imfFactor = Exp({mantissa: markets[address(asset)].imfFactorMantissa});
23
vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});
24
​
25
// Get the normalized price of the asset
26
vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);
27
28
if (vars.oraclePriceMantissa == 0) {
29
return (Error.PRICE_ERROR, 0, 0);
30
}
31
32
vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});
33
34
vars.precomputeTokens = mul_ScalarTruncate(vars.exchangeRate, vars.cTokenBalance);
35
36
vars.postIMFSize = mul_ScalarTruncate(vars.imfFactor, sqrt(vars.precomputeTokens));
37
38
vars.modCollateralFactor = mul_ScalarTruncate(vars.collateralFactor, 1e18);
39
​
40
vars.preMinDenum = (1000000000000000000 + mul_(1000000000, vars.postIMFSize));
41
​
42
vars.preMinEnum = 1100000000000000000;
43
44
vars.preMin = div_(mul_(vars.preMinEnum, 1e18), vars.preMinDenum);
45
​
46
vars.getMin = min(vars.modCollateralFactor, vars.preMin);
47
48
//convertGetMin to Exp
49
vars.convertedGetMin = Exp({mantissa: vars.getMin});
50
51
// Pre-compute a conversion factor from tokens -> ether (normalized price value)
52
vars.tokensToDenom = mul_(mul_(vars.convertedGetMin, vars.exchangeRate), vars.oraclePrice);
53
​
54
// sumCollateral += tokensToDenom * cTokenBalance
55
vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);
56
57
// sumBorrowPlusEffects += oraclePrice * borrowBalance
58
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects);
59
​
60
// Calculate effects of interacting with cTokenModify
61
if (asset == cTokenModify) {
62
// redeem effect
63
// sumBorrowPlusEffects += tokensToDenom * redeemTokens
64
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects);
65
​
66
// borrow effect
67
// sumBorrowPlusEffects += oraclePrice * borrowAmount
68
vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects);
69
}
70
}
71
​
72
// These are safe, as the underflow condition is checked first
73
if (vars.sumCollateral > vars.sumBorrowPlusEffects) {
74
return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);
75
} else {
76
return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);
77
}
78
}
Copied!
​

​

​
Last modified 12d ago