|
1 |
| -# Euler Swap |
| 1 | +# EulerSwap |
2 | 2 |
|
3 |
| -EulerSwap is an Automated Market Maker (AMM) that uses [Euler Vaults](https://docs.euler.finance/euler-vault-kit-white-paper/) as leveraged lending products in order to extend the range of its reserves and thereby improve the capital efficiency of liquidity provisioning. |
| 3 | +EulerSwap is an Automated Market Maker (AMM) that uses [Euler lending vaults](https://docs.euler.finance/euler-vault-kit-white-paper/) as leveraged lending products in order to extend the range of its reserves and thereby improve the capital efficiency of liquidity provisioning. |
4 | 4 |
|
5 |
| -To swappers, Maglev presents a hopefully familiar Uniswap2-style interface but internally it supports borrow and repaying, custom pricing curves, and other advanced functionality. Although useable by anyone, it is primarily intended to be invoked by sophisticated actors such as swap aggregators, intents solvers, and MEV bots. Similar to Uniswap, there is a careful separation between the critical core functionality for servicing swaps and the surrounding periphery functions for quoting, etc. |
| 5 | +To swappers, EulerSwap presents a hopefully familiar Uniswap2-style interface but internally it supports borrow and repaying, custom pricing curves, and other advanced functionality. Although useable by anyone, it is primarily intended to be invoked by sophisticated actors such as swap aggregators, intents solvers, and MEV bots. Similar to Uniswap, there is a careful separation between the critical core functionality for servicing swaps and the surrounding periphery functions for quoting, etc. |
6 | 6 |
|
7 |
| -<!-- TOC FOLLOWS --> |
8 |
| -<!-- START OF TOC --> |
9 |
| -<!-- DO NOT EDIT! Auto-generated by md-toc: https://github.com/hoytech/md-toc --> |
| 7 | +For more information, refer to the [white paper](./docs/white-paper/EulerSwap_White_Paper.pdf). |
10 | 8 |
|
11 |
| -- [Concept](#concept) |
12 |
| -- [Operation](#operation) |
13 |
| - - [Usage](#usage) |
14 |
| - - [Virtual Reserves](#virtual-reserves) |
15 |
| - - [Desynchronised Virtual Reserves](#desynchronised-virtual-reserves) |
16 |
| -- [Curves](#curves) |
17 |
| - - [Constant Sum](#constant-sum) |
18 |
| - - [Constant Product](#constant-product) |
19 |
| -- [License](#license) |
| 9 | +## Usage |
20 | 10 |
|
21 |
| -<!-- END OF TOC --> |
| 11 | +EulerSwap comes with a comprehensive set of tests written in Solidity, which can be executed using Foundry. |
22 | 12 |
|
23 |
| -## Concept |
| 13 | +To install Foundry: |
24 | 14 |
|
25 |
| -Given a fixed size investment, EulerSwap aims to increase the size of trades that can be serviced, relative to a conventional AMM such as Uniswap. It does this by borrowing the "out token" and collateralising this loan with the received "in token". Later on, when somebody wishes to swap in the reverse direction, the loan can be repaid in exchange for receiving the collateral, unwinding the borrow position. |
| 15 | +```sh |
| 16 | +curl -L https://foundry.paradigm.xyz | bash |
| 17 | +``` |
26 | 18 |
|
27 |
| -Because the total size of the position can be many times larger than the initial investment (depending on how much LTV/leverage is allowed on the underlying lending pools), the swap fees earned are multiplied. |
| 19 | +This will download foundryup. To start Foundry, run: |
28 | 20 |
|
29 |
| -The down-side is that while the AMM holds this leveraged position, it is paying interest on the loan. Fortunately, this is partially compensated by the fact that the AMM is simultaneously earning interest on the collateral. In some cases, this interest rate spread can be reduced further (occasionally even going negative) by taking advantage of incentives such as points/rewards. |
| 21 | +```sh |
| 22 | +foundryup |
| 23 | +``` |
30 | 24 |
|
31 |
| -## Operation |
| 25 | +To clone the repo: |
32 | 26 |
|
33 |
| -Since the level of acceptable borrowing risk may not be the same for every user, pooled deposits are not yet possible, and each EulerSwap instance manages funds for a single user (who of course may operate on behalf of pooled funds). |
| 27 | +```sh |
| 28 | +git clone https://github.com/euler-xyz/euler-swap.git && cd euler-swap |
| 29 | +``` |
34 | 30 |
|
35 |
| -EulerSwap is a contract designed to be used as an [EVC operator](https://evc.wtf/docs/whitepaper/#operators). This means that the user, known as the _holder_, does not give up control over their funds to a smart contract, but instead retains it in their wallet. The holder can be any compatible address, including standard multisig wallets or even an EOA. |
| 31 | +## Testing |
36 | 32 |
|
37 |
| -### Usage |
| 33 | +### in `default` mode |
38 | 34 |
|
39 |
| -The following are the high-level steps required to use EulerSwap: |
| 35 | +To run the tests in a `default` mode: |
40 | 36 |
|
41 |
| -- Deposit funds into one or both of the vaults |
42 |
| -- Deploy the desired EulerSwap contract, choosing parameters such as the vaults and the desired `fee` |
43 |
| -- Calculate the desired [virtual reserves](#virtual-reserves) and set these values by invoking `setVirtualReserves()` |
44 |
| -- Install the EulerSwap contract as an operator for your account |
45 |
| -- Invoke the `configure()` function on the EulerSwap contract |
| 37 | +```sh |
| 38 | +forge test |
| 39 | +``` |
46 | 40 |
|
47 |
| -At this point, anyone can invoke `swap()` on the EulerSwap contract, and this will perform borrowing and transferring activity between the two vaults. |
| 41 | +### in `coverage` mode |
48 | 42 |
|
49 |
| -### Debt Limits |
| 43 | +```sh |
| 44 | +forge coverage |
| 45 | +``` |
50 | 46 |
|
51 |
| -The initial deposits in the vaults represent the initial investment, and are swapped back and forth in response to swapping activity. In a conventional AMM such as Uniswap, these balance are called _reserves_. However, if swapping was constrained to these assets alone, then this would imply a hard limit on the size of swaps that can be serviced. To increase the effective funds, EulerSwap AMMs are configured with _virtual reserves_. These are typically larger than the size of the conventional reserves, which signifies that not only can all the assets be swapped from one vault to another, but even more assets can be borrowed on the EulerSwap's account. |
| 47 | +## Safety |
52 | 48 |
|
53 |
| -Virtual reserves control the maximum debt that the EulerSwap contract will attempt to acquire on each of its two vaults. Each vault can be configured independently. |
| 49 | +This software is experimental and is provided "as is" and "as available". |
54 | 50 |
|
55 |
| -For example, if the initial investment has a NAV of $1000, and virtual reserves are configured at $5000 for each vault, then the maximum LTV loan that the AMM will support will be `5000/6000 = 0.8333`. In order to leave a safety buffer, it is recommended to select a maximum LTV that is below the borrowing LTV of the vault. |
| 51 | +No warranties are provided and no liability will be accepted for any loss incurred through the use of this codebase. |
56 | 52 |
|
57 |
| -Note that it depends on the [curve](#curves) if the maximum LTV can actually be achieved. A constant product will only approach these reserve levels asymptotically, since each unit will get more and more expensive. However, with constant sum, this LTV can be achieved directly. |
| 53 | +Always include thorough tests when using EulerSwap to ensure it interacts correctly with your code. |
58 | 54 |
|
59 |
| -### Desynchronised Reserves |
| 55 | +## Known limitations |
60 | 56 |
|
61 |
| -The EulerSwap contract tracks what it believes the reserves to be by caching their values in storage. These reserves are updated on each swap. However, since the balance is not actually held by the EulerSwap contract (it is simply an operator), the actual underlying balances may get out of sync. This can happen gradually as interest is accrued, or suddenly if the holder moves funds or the position is liquidated. |
| 57 | +Refer to the [white paper](./docs/white-paper/EulerSwap_White_Paper.pdf) for a list of known limitations and security considerations. |
62 | 58 |
|
63 |
| -When this occurs, the `syncVirtualReserves()` should be invoked. This determines the actual balances (and debts) of the holder, and adjusts them by the configured virtual reserve levels. |
| 59 | +## Contributing |
64 | 60 |
|
65 |
| -## Curves |
66 |
| - |
67 |
| -### Constant Sum |
68 |
| - |
69 |
| -This "curve" simply adds the values of the two reserves together and ensures that after a swap this sum has not decreased. This curve is mostly suitable for assets that are pegged to the same value, such as stable/stable pairs. |
70 |
| - |
71 |
| -This curve supports a price fraction so that the two tokens can have different relative values, which can be useful if the peg is other than 1:1, or if the tokens have differing decimals. |
72 |
| - |
73 |
| -In this curve, the entire virtual reserves can be consumed, and since each marginal unit of the swap has the same price, there is no direct incentive to deleverage the position. However, for the same reason this does allow fixed fees for swaps of any allowed size (fixed price impact). |
74 |
| - |
75 |
| -### Constant Product |
76 |
| - |
77 |
| -This is the traditional Uniswap2 curve that preserves the product of the two reserves. The larger a swap, the higher the price impact and the more profitable it is to arbitrage a disbalanced pool back to its wider market price. |
| 61 | +The code is currently in an experimental phase. Feedback or ideas for improving EulerSwap are appreciated. Contributions are welcome from anyone interested in conducting security research, writing more tests including formal verification, improving readability and documentation, optimizing, simplifying, or developing integrations. |
78 | 62 |
|
79 | 63 | ## License
|
80 | 64 |
|
|
0 commit comments