curve-cross-asset-swaps
curve-cross-asset-swaps copied to clipboard
Cross asset swaps using Curve and Synthetix
curve-cross-asset-swaps
Cross asset swaps using Curve and Synthetix.
Overview
SynthSwap combines Curve and Synthetix to allow large scale swaps between different asset classes with minimal slippage. Utilizing Synthetix' zero-slippage synth conversions and Curve's deep liquidity and low fees, we can perform fully on-chain cross asset swaps at scale with a 0.38% fee and minimal slippage.
How it Works
As an example, suppose we have asset A and wish to exchange it for asset D. For this swap to be possible, A and D must meet the following requirements:
- Must be of different asset classes (e.g. USD, EUR, BTC, ETH)
- Must be exchangeable for a Synthetic asset within one of Curve's pools (e.g. sUSD, sBTC)
The swap can be visualized as A -> B -> C | C -> D:
- The initial asset
Ais exchanged on Curve forB, a synth of the same asset class. Bis converted toC, a synth of the same asset class asD.- A settlement period passes to account for sudden price movements between
BandC. - Once the settlement period has passed,
Cis exchanged on Curve for the desired assetD.
These swaps cannot occur atomically due to the settlement period. SynthSwap mints an ERC721 non-fungible token to represent the claim on each unsettled swap.
- The token, and associated right to claim, are fully transferable
- Upon completion of the swap the NFT is burned
- Each NFT has a unique token ID that is never re-used
- Token IDs are not sequential
Considerations
The benefits from these swaps are most apparent when the exchange amount is greater than $1m USD equivalent. As such, the initiation of a swap gives a strong indicator other market participants that a 2nd post-settlement swap will be coming. We attempt to minimize the risks from this in several ways:
Dis not declared on-chain when performing the swap fromA -> C.- It is possible to perform a partial swap from
C -> D, and to swap into multiple final assets. The NFT persists until it has no remaining underlying balance ofC. - There is no fixed time frame for the second swap. A user can perform it immediately or wait until market conditions are more favorable.
- It is possible to withdraw
Cwithout performing a second swap. - It is possible to perform additional
A -> B -> Cswaps to increase the balance of an already existing NFT.
The range of available actions and time frames make it significantly more difficult to predict the outcome of a swap and trade against it.
Technical Implementation
Settlers
Unsettled synthetic assets cannot be transferred because the settled balance is not yet known. If any portion of a synth balance at an address is unsettled, the entire balance is frozen. Thus, to allow multiple swaps at the same time there is a requirement to hold each synth balance in a unique address. We achieve this using Vyper's create_forwarder_to to deploy proxy contracts which handle the synth swap. These contracts are referred to as "settlers".
The Settler implementation contract is deployed prior to SynthSwap. Several settler proxies are deployed during the constructor of SynthSwap. Settlers are re-used for subsequent swaps to reduce gas costs. A new settler is only deployed when all existing settlers are currently in use.
Each NFT token ID is a uint256 representation of [16 byte nonce][20 byte settler address]. The nonce starts at zero and is incremented each time a settler is re-used in order to ensure a unique token ID for each swap.
Usage
Dependencies
- python3 version 3.6 or greater, python3-dev
- brownie - tested with version 1.12.4
- brownie-token-tester
- ganache-cli - tested with version 6.12.1
Testing
Testing is performed in a forked mainnet environment. The test suite is broadly split between unit and integration tests.
To run the unit tests:
brownie test tests/unitary
To run the integration tests (this might take a while):
brownie test tests/integration
Deployment
To deploy the contracts, first modify the deployment script to unlock the account you wish to deploy from. Then:
brownie run deploy --network mainnet
License
This repository is licensed under the MIT license.