Skip to content

Latest commit

 

History

History
111 lines (96 loc) · 5.8 KB

README.md

File metadata and controls

111 lines (96 loc) · 5.8 KB

Leveraged AMM Exchange Module

Introduction

  • These contracts are simplified version of a leveraged AMM exchange.
    • This exchange has the logic of an AMM exchange module: (Rt + x) * (Ru + y) = Rt * Ru.
  • The contracts allow users to deposit/withdraw ERC20 tokens and swap tokens with leverage up to 10x.
  • The contracts allow users to create arbitrary trading pairs (the swapped asset is called position).
  • The contracts emit events for deposit, withdraw and swap functions.
  • The contracts also provide a set of view functions, which can
    • input asset A amount as the payment and the leverage => output asset B amount after the swap
    • input asset B amount to exchange for and the leverage => output asset A amount you should pay for
    • returns the remaining value of the account
  • Users can open/reduce and open/close positions in cross and isolated margin modes, respectively.
    • In cross margin mode, the user's position is shared across all token swaps.
      • OPEN: buy tokens, REDUCE: sell tokens (part of or all).
    • In isolated margin mode, the user's position is isolated to each token swap.
      • OPEN: buy tokens, CLOSE: sell tokens in a specific single swap (all).
  • A simple Web GUI (HTML) is also provided to interact with the contracts.

Installation & Setup

Framework

This project is established by Foundry framework. For installation, please refer to Official Foundry Book.

  • Compile the Leveraged AMM Exchange Module contracts in the folder src/.
$ forge compile # or `forge build`
  • Run the unit tests for the contracts, which are located in the folder test/.
$ forge test
================================================================================

[PASS] testFuzz_Deposit(uint256) (runs: 256, μ: 96684, ~: 97247)
[PASS] testFuzz_Withdraw(uint256) (runs: 256, μ: 110898, ~: 111472)
[PASS] test_AddReserves() (gas: 148919)
[PASS] test_AddReserves_Failed() (gas: 159666)
[PASS] test_CreatePair() (gas: 154154)
[PASS] test_CreatePair_Failed() (gas: 165411)
[PASS] test_Deposit() (gas: 96861)
[PASS] test_Deposit_Failed() (gas: 27677)
[PASS] test_Withdraw() (gas: 119422)
[PASS] test_Withdraw_Failed() (gas: 101115)
[PASS] test_GetAccountRemainingValue() (gas: 234000)
[PASS] test_GetAmountCollateralReturn() (gas: 184418)
[PASS] test_GetAmountInForOut() (gas: 172022)
[PASS] test_GetAmountOutFromIn() (gas: 165341)
[PASS] test_GetPairPrice() (gas: 156486)
[PASS] test_GetPositionId() (gas: 138955)
[PASS] test_MaxLeverage() (gas: 12037)
[PASS] test_Swap_Open_CrossMode() (gas: 428795)
[PASS] test_Swap_Reduce_CrossMode() (gas: 407240)
[PASS] test_Swap_Open_IsolatedMode() (gas: 906676)
[PASS] test_Swap_Close_IsolatedMode() (gas: 392260)
[PASS] test_Swap_Failed() (gas: 118890)
  • Run the following command to see the testing coverage, which is also listed below.
$ forge coverage --ir-minimum --skip src/tests/*.sol script/*.sol
================================================================================

Ran 2 test suites in 395.11ms (766.41ms CPU time): 40 tests passed, 0 failed, 0 skipped (40 total tests)
| File                                     | % Lines          | % Statements     | % Branches     | % Funcs         |
|------------------------------------------|------------------|------------------|----------------|-----------------|
| src/LeveragedAMMExchange.sol             | 100.00% (50/50)  | 96.77% (90/93)   | 86.36% (19/22) | 100.00% (12/12) |
| src/LeveragedAMMExchangeCrossMode.sol    | 97.78% (44/45)   | 93.44% (57/61)   | 81.25% (13/16) | 100.00% (7/7)   |
| src/LeveragedAMMExchangeIsolatedMode.sol | 97.92% (47/48)   | 94.03% (63/67)   | 75.00% (9/12)  | 100.00% (8/8)   |
| Total                                    | 98.60% (141/143) | 95.02% (210/221) | 82.00% (41/50) | 100.00% (27/27) |

Deploy Contracts on Local Network

  • To use the Web GUI, you should deploy the contracts on local blockchain network by Anvil in Foundry.
    • src/ILeveragedAMMExchange.sol
    • src/LeveragedAMMExchange.sol
    • src/LeveragedAMMExchangeCrossMode.sol
    • src/LeveragedAMMExchangeIsolatedMode.sol
    • src/tests/MyToken.sol
  • Firstly, open another terminal and execute Anvil to run local network (by default setting).
  • Make sure you have Metamask installed in the web browser
$ anvil
  • Rename the file .env.example with .env, copy one of the private key from the Anvil and paste it in .env.
  • Insert the chosen private key into Metamask and check whether there is some ETH in this account.
    • WARNING: DO NOT TAKE THE PRIVATE KEY AS YOUR OWN WALLET AND PUT THE REAL MONEY INTO IT.
  • After updating the .env file, run the following commands to load the env variables and deploy the contracts.
$ source .env
$ forge script script/LeveragedAMMExchange.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY
  • Now, we need to update the new contract addresses to the Web GUI config.
  • A simple script is provided to write the config (html/contract-address.json) automatically.
$ node load-address.js
  • Install the VSCode extension: Live Server.
    • This can open the HTML files in a convenient way - like running on a web server.
  • Right click on files: html/exch-isolated-mode.html & html/exch-cross-mode.html => Open with Live Server The screenshot of the Web GUI

Static Analysis

  • The contracts have been scanned by the static analysis tool Slither.
    • The reporting result from Slither is located in the folder report/.