A decentralized foreign exchange protocol optimized for stablecoins.
DFX v2 is an update from DFX protocol v0.5 with some additional features including the protocol fee, which is set by the percentage of the platform fee(which incurs for each swap on all the pools across the platform), fixing issues of invariant check, and the support of flashloans. The major change from the previous version is, V2 is more generalized for users, meaning anybody can create their curves(pools) while V0.5 only allowed the DFX team to create pools.
There are two major parts to the protocol: Assimilators and Curves. Assimilators allow the AMM to handle pairs of different value while also retrieving reported oracle prices for respective currencies. Curves allow the custom parameterization of the bonding curve with dynamic fees, halting bounderies, etc.
Assimilators are a key part of the protocol, it converts all amounts to a "numeraire" which is essentially a base value used for computations across the entire protocol. This is necessary as we are dealing with pairs of different values. AssimilatorFactory is responsible for deploying new AssimilatorV2.
Oracle price feeds are also piped in through the assimilator as they inform what numeraire amounts should be set. Since oracle price feeds report their values in USD, all assimilators attempt to convert token values to a numeraire amount based on USD.
High level overview.
Name | Description |
---|---|
Weights | Weighting of the pair (only 50/50) |
Alpha | The maximum and minimum allocation for each reserve |
Beta | Liquidity depth of the exchange; The higher the value, the flatter the curve at the reported oracle price |
Delta/Max | Slippage when exchange is not at the reported oracle price |
Epsilon | Fixed fee |
Lambda | Dynamic fee captured when slippage occurs |
In order to prevent anti-slippage being greater than slippate, DFX V2 requires deployers to set Lambda to 1(1e18).
For a more in-depth discussion, refer to section 3 of the shellprotocol whitepaper
The main changes between V2 and the original code can be found in the following files:
AssimilatorV2.sol
CurveFactoryV2.sol
CurveMath.sol
ProportionalLiquidity.sol
Swaps.sol
Structs.sol
In the original implementation, all pools are assumed to be baskets of like-valued tokens. In our implementation, all pools are assumed to be pairs of different-valued FX stablecoins (of which one side is always USDC).
This is achieved by having custom assimilators that normalize the foreign currencies to their USD counterparts. We're sourcing our FX price feed from chainlink oracles. See above for more information about assimilators.
Withdrawing and depositing related operations will respect the existing LP ratio. As long as the pool ratio hasn't changed since the deposit, amount in ~= amount out (minus fees), even if the reported price on the oracle changes. The oracle is only here to assist with efficient swaps.
Flashloans live in every curve contract produced by the CurveFactory. DFX curve flash function is based on the the flashloan model in UniswapV2. The user calling flash function must conform to the IFlash.sol
interface. It must containing their own logic along with code to return the correct amount of tokens requested along with its respective fee. Flash function will check for the balances of the curve before and after to ensure that the correct amount of fees has been sent to the treasury as well as funds returned back to the curve.
Install Foundry
Download all dependencies.
forge install
Run Ethereum mainnet forked testnet on your local in one terminal:
anvil -f https://mainnet.infura.io/v3/<INFURA KEY> --fork-block-number 15129966
In another terminal, run V2 test script:
forge test --match-contract V2Test -vvv -f http://127.0.0.1:8545
Run Protocol Fee test:
forge test --match-contract ProtocolFeeTest -vvv -f http://127.0.0.1:8545
V2.t.sol
testDeployTokenAndSwap
gold
token) and it's price oralce (gold oracle
), gold : usdc ratio is set to 1:20 in the testgold
and usdc
testForeignStableCoinSwap
testTotalSupply
testSwapDifference
testInvariant
ProtocolFee.t.sol
testProtocolFeeUsdcCadcSwap
protocol fee
)protocol fee
is calculated by the following formular
protocol fee = platform fee * CurveFactoryV2.protocolFee / 100000
if protocolFee is set to 50,000 (50% because of 6 decimal places), then the platform fee is divided evenly to the treasury & curve
Router.t.sol
testTargetSwap
testOriginSwap
Flashloan.t.sol
testFlashloan
flash
functiontestFail_FlashloanFee
testFail_FlashloanCurveDepth
CurveFactoryV2.t.sol
testFailDuplicatePairs
testNewPairs
testUpdateFee
testFailUpdateFee
testUpdateTreasury