Introduce and analyze Fixed Forex contract
Recently Andre Cronje, Defi KOL, announce the new project: Fixed Forex. It is a new project, so the document is not complete, just only introducing an article on Medium。 Fixed Forex include some features, include
- 0 governance (or multisig)
- 0 configuration
- 0 fees
- 0 value extraction
- Gentle liquidations
- Dynamic minting caps based on on-chain liquidity
- Dynamic LTVs based on on-chain protocols
I am very interested in this project, so I take a look at the contract code and do some research. Try to understand how to implement these features and the contract how work. Before we go through the contract, there is some information about the contract below. By the way, I can not sure the FixedUSD contract can represent all FixedForex contracts or not. But it is the only FixedForex contract I can survey. Maybe other FixedForex contracts will differ from the FixedUSD contract.
FixedUSD:
- Address: 0x92fc8e6efdf389e2527d14393b15f543f9a03420
- config:
- oracle = 0xDA7a001b254CD22e46d3eAB04d937489c93174C3
- stable = DAI
- router = SushiSwapRouter
- aavev2 = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9
- iron back = 0xAB1c342C7bf5Ec5F02ADEA1c2270670bCa144CbB
- unitProcotol = 0x203153522B9EAef4aE17c6e99851EE7b2F7D312E
What are Loan-to-value ratios?
Loan to Value Ratio (LTV) is how lenders describe the amount you need to borrow to buy a particular property. In a nutshell: it’s the amount you need to borrow, calculated as a percentage of the property’s ‘lender-assessed value’.
Let’s talk about FixedForex how to work by mint operation and liquidate operation.
How to mint FUSD
There are two ways to mint FUSD. one is the mint()
function, another is mintArb()
.
function mint(address asset, uint amount, uint minted)
function mint(address asset, uint amount, uint minted)
- asset: collateral asset
- amount: collateral asset amount, only mint if amount is zero
- minted: minted FUSD amount, only add collateral if minted is zero
You can mint FUSD with your collateral through mint() of contract. For example, using USDT as collateral to mint FUSD. The main flow will be :
- Transfer USDT from sender to FixedUSD contract
- Add
amount
to sender USDT collateral callcollateral[sender][USDT]
and total USDT collateral callcollaterals[USDT]
- Add
minted
to sender USDT credit callcredit[sender][USDT]
and total USDT credit callcredit[USDT]
.credit[sender][USDT]
means how much FUSD is mined under sender USDT collateral.credit[USDT]
means how much FUSD is mined under total USDT collateral. - Check
collaterals[USDT]
≥credit[USDT]
. Calculate the equivalentDAI
value undercollaterals[USDT]
throughSushiswap
.credit[USDT]
means how much FUSD is minted under the USDT collateral. - Calculate sender’s mint FUSD power under USDT collateral. More detail in below.
- Check sender mint FUSD power ≥
credit[sender][USDT]
- mint
minted
amount FUSD to sender
How to calculate the sender’s mint FUSD power under the single collateral asset value?
- Get USDT to USD
rate
throughOracle
- Get asset
LTV
. It will get LTV from 3 protocols now. Iron bank, AaveV2, and Unit Protocol. Choose max LTV as asset LTV - Max mint FUSD =
rate * sender collateral amount * LTV
function mintArb(uint amount)
function mintArb(uint amount) external
- amount: DAI amount
Another way is mintArb()
. But it is easier than mint()
. You just deposit DAI to mint FUSD. Deposit 1 DAI then get 1 FUSD(1 DAI = 1 FUSD).
Step:
- Transfer DAI form sender to FixedUSD contract
- Mint
amount
FUSD to sender
How to Liquidate
function liquidate(address owner, address asset, uint max)
function liquidate(address owner, address asset, uint max)
- owner: Who will be liquidiated
- asset: Liquidiated asset
- max: The maximum FUSD you want to pay
Main Step: (We still supposed USDT as collateral.)
- Get total USDT amount of owner as collateral, call
nomial
. - Get the minted FUSD power of USDT amount, call
backend
. - Get minted FUSD of sender under USDT collateral, call
debt
. - Check
debt
≥backend
. - Calculate how much FUSD needs to be repaid, call
repayment
. It will get the LTV of USDT and depend on the LTV level to calculaterepayment
.
repayment:
LTV = 60 => min(3.1 * (debt-backend), debt)
LTV = 65 => min(3.7 * (debt-backend), debt)
LTV = 70 => min(4.6 * (debt-backend), debt)
LTV = 75 => min(6.1 * (debt-backend), debt)
LTV = 80 => min(9.1 * (debt-backend), debt)
LTV = 85 => min(18.1 * (debt-backend), debt)
LTV >= 90 => debt
8. Check repayment
≤ max
9. Calculate how much USDT needs to pay for the Liquidator, call payment
. More detail in below.
10. Burn Liquidator’s FUSD
11. Update collateral information
12. Send payment
USDT to Liquidator
How to calculate how much collateral can be got by Liquidator
- Get USDT to USD
rate
byOracle
,(rate == 1)
- Get
LookupLiq = rate * nomial * (_LIQUIDATION_VALUE/_BASE == 0.9)
payment = (repayment * nomial) / (rate * nomial * 0.9) = 1.11 * repayment
Summary
It tries to make a stable coin from another angle. no token, no fee, no governance. It is like a more experimental project and no audit. FixedForex is a very interesting project. But I think there are a few things to be noticed.
- The Oracle can provide different rates like USD, EUR, ZAR, JPY, CNY, etc. Need to notice how to oracle work.
- Any asset can be as collateral if the asset is collateral on aaveV2, iron bank, or Unit Protocol.
- It will also update Calculate LTV and Liquidity to cache. But the cache timeout is 1 day. It could be non-sync with Market.
mintArb()
allow user deposit DAI to mint FUSD (FUSD: DAI = 1: 1)。 It helps to stabilize the FUSD price. It also could help Liquidator to mint FUSD to liquidate.
Reference: