-
Notifications
You must be signed in to change notification settings - Fork 1
Synthetic Asset
Assets supported by the Flow Protocols are implemented as fToken ERC-20 compliant smart contracts. The Flow Synthetic Asset Protocol is the control protocol for minting fTokens and for depositing fTokens to earn interest. There can be multiple liquidity pool available for each fToken, and users could choose at their own discretion based on spread and/or other factors. Users would primarily interact with the Flow Synthetic Asset Protocol to mint, redeem, deposit, withdraw, liquidate a position.
The mint function transfers users' USD into the fToken's collateral, then transfers the over collateral amount from selected liquidity pool into the collateral, and puts a certain amount into money market to start accumulating interest. The number of fToken minted is determined by the ask price of the designated pool. The amount to put into the money market is calculated based on minimum liquidity requirement.
function mint(FlowToken token, LiquidityPoolInterface pool, uint baseTokenAmount) returns (uint)
-
msg.sender
: the account supplying DAI in exchange for fToken -
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
pool
: the account of a liquidity pool chosen by the user -
baseTokenAmount
: amount of DAI to exchange -
return
: amount of fToken minted
Before supplying DAI, users must first approve the Flow Synthetic Asset Protocol to access their DAI balance.
await usd.approve(protocol.address, constants.MAX_UINT256, { from: alice });
const buy = (addr: string, amount: number) => () => protocol.mint(fToken.address, liquidityPool.address, amount, { from: addr });
The redeem function returns the USD base token to user based on the bid price of chosen liquidity pool, refunds the collateral amount of this position to the pool plus any interest earned during the period.
function redeem(FlowToken token, LiquidityPoolInterface pool, uint flowTokenAmount) returns (uint)
-
msg.sender
: the account supplying fToken in exchange for DAI -
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
pool
: the account of a liquidity pool chosen by the user -
flowTokenAmount
: amount of fToken to exchange -
return
: amount of DAI
Max amount of fToken can be minted for a given liquidity pool, is equal to
maxMint = liquidity / additionalCollateralRatio
All liquidity is converted and managed as iToken e.g. iUSD in the money market.
liquidity = iToken.balanceOf(poolAddress)
Each liquidity pool can set a higher collateral ratio than the fToken default for extra security.
additionalCollateralRatio = pool.getAdditionalCollateralRatio();
Max amount of fToken can be sold to a given liquidity pool, is equal to total fToken minted by the pool
{collateral, minted} = fToken.getPosition(poolAddress)
maxRedeem = minted;
When actual collateral ratio is less than the liquidation ratio, then the positions are open for public liquidation. The liquidate function sells given amount of fToken for DAI, transfers the DAI and a small amount of incentive reward to the liquidator, and refunds the pool with remaining collateral. For example, if liquidation ratio is at 5%, then when public liquidation is open, the position is still over-collateralized, say at 4.9%. Then the incentive will be taken out of the 4.9% collateral, while the remaining returns to the pool.
function liquidate(FlowToken token, LiquidityPoolInterface pool, uint flowTokenAmount) returns (uint)
-
msg.sender
: the liquidator -
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
pool
: the account of a liquidity pool chosen by the user -
flowTokenAmount
: amount of fToken to exchange -
return
: amount of DAI exchanged plus incentive
The deposit function mints certain amount of interest share for the user to account for interest accumulated hereafter.
function deposit(FlowToken token, uint flowTokenAmount)
-
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
flowTokenAmount
: amount of fToken to deposit
Interest earned for a given account is equal to
interest earned in DAI = interestShares * interestShareExchangeRate / 10^18 - interestDebit
function interestShareExchangeRate() public view returns (uint)
mapping (address => uint) public interestShares
mapping (address => uint) public interestDebits
The withdraw function returns fToken plus interest earned in DAI to user
function withdraw(FlowToken token, uint flowTokenAmount) returns (uint)
-
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
flowTokenAmount
: amount of fToken to withdraw -
return
: withdrawn fToken plus interest earned
The getAdditionalCollateralRatio functions returns the maximum of two - the fToken's default collateral ratio and the designated liquidity pool's collateral ratio. A liquidity can set a higher collateral ratio than default for extra security.
function getAdditionalCollateralRatio(FlowToken token, LiquidityPoolInterface pool)
-
token
: the account of a fToken, e.g. address of deployed fEUR or fJPY -
flowTokenAmount
: amount of fToken to withdraw
The getPosition function returns the collaterals and minted fToken for a given liquidity pool.
function getPosition(address poolAddr) external view returns (uint collaterals, uint minted)
-
poolAddr
: the account of a liquidity pool -
return collaterals
: collaterals locked in unit of DAI -
return minted
: amount of fToken minted from given pool
The deposits map returns total deposited fToken amount for a given account.
mapping (address => uint) public deposits
The defaultCollateralRatio is the default additional collateral ratio for the fToken. For example, if the defaultCollateralRatio is 10%, when minting $100 worth fToken, then additional $10 is required from the liquidity pool to over-collateralized the fToken position.
Percentage.Percent public defaultCollateralRatio;
The liquidationCollateralRatio is the threshold below which the fToken positions will be open to public liquidation.
Percentage.Percent public liquidationCollateralRatio;
The extremeCollateralRatio is the threshold below which all available collateral from liquidity pool will be rewarded to the liquidator as extra layer of protection.
Percentage.Percent public extremeCollateralRatio;
The actual collateral ratio given current price feed from oracle is equal to
actualCollateralRatio = collaterals / (minted * oracle.getPrice())