Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AMM: Swap and add liquidity scripts #312

Merged
merged 44 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8b64676
create new script project
supiket Dec 2, 2022
40f5f43
correct contract call, add comments, remove unused imports
supiket Dec 3, 2022
d3a3d1d
misc improvements to the script
supiket Dec 3, 2022
0722431
add test module with utils and a passing test!!!
supiket Dec 3, 2022
8ea8638
Merge branch 'master' into supiket/swap-route-script
supiket Dec 3, 2022
1c40ea8
add empty line
supiket Dec 3, 2022
ef9b556
remove _Meta_ from test helper structs
supiket Dec 5, 2022
bab24e0
Merge branch 'master' into supiket/swap-route-script
supiket Dec 5, 2022
57af372
fmt
supiket Dec 5, 2022
d0eae8a
add test utils
supiket Dec 6, 2022
fdb3fa6
Merge branch 'master' into supiket/swap-route-script
supiket Dec 6, 2022
731a59f
dev dependencies reorder
supiket Dec 6, 2022
014ff68
update cargo dependencies
supiket Dec 6, 2022
ceef4f5
add swap exact output script
supiket Dec 7, 2022
e95c80b
improve test utils setup
supiket Dec 8, 2022
ddf4309
improve test utils
supiket Dec 8, 2022
c21cf86
tests: add transaction parameters struct for creating transactions
supiket Dec 9, 2022
60c106b
rename contract errors
supiket Dec 10, 2022
0d45477
improve preview add liquidity function
supiket Dec 10, 2022
a24d455
add atomic deposit and add liquidity script
supiket Dec 10, 2022
566ad54
add comments, rename some variables
supiket Dec 10, 2022
ed63bfe
Merge branch 'master' into supiket/swap-route-script
supiket Dec 10, 2022
4e85b14
increase test coverage of scripts
supiket Dec 12, 2022
548cc3b
update readme and specs
supiket Dec 12, 2022
51a7252
replace revert signal with error messages in swap script tests
supiket Dec 12, 2022
ed729e5
apply code suggestions
supiket Dec 16, 2022
ecee814
change `fuels` dependency that fixes the revert test issue
supiket Dec 20, 2022
e8daa8a
add tests to atomic deposit and add liquidity script
supiket Dec 21, 2022
9e6ce18
Merge branch 'master' into supiket/swap-route-script
supiket Dec 21, 2022
fffc755
rename `abi.rs` to `interface.rs`
supiket Dec 21, 2022
5785730
Merge branch 'master' into supiket/swap-route-script
supiket Dec 21, 2022
d46fd1a
make fuels depend on master
supiket Jan 2, 2023
1d7e835
add panic message
supiket Jan 2, 2023
7a240a9
remove unnecessary types, alphabetical reorder, rename a field
supiket Jan 2, 2023
333e51c
rework exchange contract storage and improve data structures
supiket Jan 2, 2023
b33f215
add liquidity script: accept struct instead of individual parameters
supiket Jan 2, 2023
5f0dfe2
refine imports, `require`s and test setups, add some comments
supiket Jan 2, 2023
907d4b3
boundary tests for swap exact input script
supiket Jan 2, 2023
46dc7f0
Merge branch 'master' into supiket/swap-route-script
supiket Jan 2, 2023
b81a421
make amm id a config-time constant, remove unused variable, update specs
supiket Jan 2, 2023
7bbc2a2
Merge branch 'master' into supiket/swap-route-script
simonr0204 Jan 3, 2023
a50e8e8
swap exact output script boundary tests
supiket Jan 4, 2023
0f05db4
unify scripts' test structures
supiket Jan 6, 2023
fe4b917
apply suggestions
supiket Jan 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AMM/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ target
project/contracts/AMM-contract/out
project/contracts/exchange-contract/out
project/contracts/exchange-contract/tests/artifacts/malicious-implementation/out
project/scripts/atomic-add-liquidity/out
supiket marked this conversation as resolved.
Show resolved Hide resolved
project/scripts/swap-exact-input/out
project/scripts/swap-exact-output/out
3 changes: 3 additions & 0 deletions AMM/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ resolver = "2"
members = [
"./project/contracts/AMM-contract",
"./project/contracts/exchange-contract",
"./project/scripts/atomic-add-liquidity",
"./project/scripts/swap-exact-input",
"./project/scripts/swap-exact-output",
]
3 changes: 3 additions & 0 deletions AMM/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ members = [
"./project/contracts/AMM-contract",
"./project/contracts/exchange-contract",
"./project/contracts/exchange-contract/tests/artifacts/malicious-implementation",
"./project/scripts/atomic-add-liquidity",
"./project/scripts/swap-exact-input",
"./project/scripts/swap-exact-output",
]
24 changes: 17 additions & 7 deletions AMM/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,29 @@ The contracts are designed to
```
AMM/
├── project/
| ── contracts/
| ── contracts/
| | ├── AMM-contract/
| | | ├── src/main.sw
| | | └── tests/harness.rs
| | └── exchange-contract/
| | ├── src/main.sw
| | └── tests/harness.rs
| └── libraries/
| └── src/interface.sw
| ├── scripts/
| | ├── atomic-add-liquidity/
| | ├── swap-exact-input/
| | └── swap-exact-output/
| ├── libraries/
| | └── src/interface.sw
| └── test-utils/
| └── src/lib.rs
├── README.md
└── SPECIFICATION.md
```

All contracts and scripts have the structure:

```
contract or script/
├── src/main.sw
└── tests/harness.rs
```

Comment on lines +47 to +54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are approaching a point where we should expand the documentation of how a project is Run.

Taking a look at the section below, Running the Project, we split devops into UI and Tests.
As a brief insight, I think we will move towards breaking that up into building the contracts, deploying them, using scripts, running tests, UI and possibly other sections for containers or anything else that is project specific.

I think this will be a separate issue that I'll need to consider a bit more so there's no need to experiment here now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this app specifically, scripts will be used in the frontend, however they have tests like contracts do.
Also worth pointing out that whether the word "scripts" refer to Sway scripts or otherwise may be ambiguous to more external people.

However I get what you mean and I agree, the Running the Project section will evolve along with our repo structure and tooling integration.

## Running the project

### User Interface
Expand Down
125 changes: 74 additions & 51 deletions AMM/SPECIFICATION.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,87 @@
Table of Contents
- [Overview](#overview)
- [Use Cases](#use-cases)
- [Actions that users are able to perform](#actions-that-users-are-able-to-perform)
- [AMM Contract](#amm)
- [Core Functionality](#core-functionality)
- [`initialize()`](#initialize)
- [`add_pool()`](#add_pool)
- [State Checks](#state-checks)
- [`pool()`](#pool)
- [Exchange Contract](#exchange)
- [Core Functionality](#core-functionality-1)
- [`constructor()`](#constructor)
- [`deposit()`](#deposit)
- [`add_liquidity()`](#add_liquidity)
- [`remove_liquidity()`](#remove_liquidity)
- [`withdraw()`](#withdraw)
- [`swap_exact_input()`](#swap_exact_input)
- [`swap_exact_output()`](#swap_exact_output)
- [Previews](#previews)
- [`preview_add_liquidity()`](#preview_add_liquidity)
- [`preview_swap_exact_input()`](#preview_swap_exact_input)
- [`preview_swap_exact_output()`](#preview_swap_exact_output)
- [State Checks](#state-checks-1)
- [`balance()`](#balance)
- [`pool_info()`](#pool_info)
- [AMM Contract](#amm-contract)
- [Core Functionality](#core-functionality)
- [`initialize()`](#initialize)
- [`add_pool()`](#add_pool)
- [State Checks](#state-checks)
- [`pool()`](#pool)
- [Exchange Contract](#exchange-contract)
- [Core Functionality](#core-functionality-1)
- [`constructor()`](#constructor)
- [`deposit()`](#deposit)
- [`add_liquidity()`](#add_liquidity)
- [`remove_liquidity()`](#remove_liquidity)
- [`withdraw()`](#withdraw)
- [`swap_exact_input()`](#swap_exact_input)
- [`swap_exact_output()`](#swap_exact_output)
- [Previews](#previews)
- [`preview_add_liquidity()`](#preview_add_liquidity)
- [`preview_swap_exact_input()`](#preview_swap_exact_input)
- [`preview_swap_exact_output()`](#preview_swap_exact_output)
- [State Checks](#state-checks-1)
- [`balance()`](#balance)
- [`pool_info()`](#pool_info)
- [Scripts](#scripts)
- [Atomic Add Liquidity](#atomic-add-liquidity)
- [Swap Exact Input](#swap-exact-input)
- [Swap Exact Output](#swap-exact-output)
- [Sequence Diagram](#sequence-diagram)

# Overview

This document provides an overview of the application.

It outlines the use cases, i.e., desirable functionality, in addition to requirements for the smart contracts.
It outlines the use cases, i.e., desirable functionality, in addition to requirements for the smart contracts and scripts.

# Use Cases

This section contains general information about the functionality of the application and thus does not touch upon any technical aspects.

If you are interested in a functional overview then this is the section for you.

## Actions that users are able to perform
## AMM Contract

This sub-section details what a user is able to do, e.g., click a button and "x, y, z" happens.
### Core Functionality

### AMM Contract

#### Core Functionality

##### `initialize()`
#### `initialize()`

1. Specifies the legitimate exchange contract implementation that the AMM will operate with (this is a safety mechanism against adding malicious exchange contract implementations to the AMM)
1. Requires bytecode root of the desired exchange contract implementation

##### `add_pool()`
#### `add_pool()`
1. Adds the liquidity pool for the specified asset pair
1. If the AMM is initialized
2. Requires the identifiers of the two assets
3. Requires the exchange contract identifier that is also the identifier of the liquidity pool asset for the given pair
1. If the exchange contract is legitimate, i.e., the bytecode root matches
2. If the exchange contract defines the pool for the specified asset pair

#### State Checks
### State Checks

##### `pool()`
#### `pool()`

1. Returns the exchange contract identifier for an asset pair
1. Requires the identifiers of the two assets

### Exchange Contract
## Exchange Contract

#### Core Functionality
### Core Functionality

##### `constructor()`
#### `constructor()`

1. Allows specifying the asset pair that the liquidity pool in the exchange contract will consist of
1. If the asset pair for the exchange contract has not already been set
2. Requires two different asset identifiers

##### `deposit()`
#### `deposit()`

1. Deposits an asset into the contract
1. If the asset pair of the pool is set
2. Requires any amount of either asset in the pair

##### `add_liquidity()`
#### `add_liquidity()`

1. Allows adding liquidity to the pool by using up at least one asset's deposited amount
1. If the asset pair of the pool is set
Expand All @@ -93,7 +92,7 @@ This sub-section details what a user is able to do, e.g., click a button and "x,
5. Requires the desired liquidity amount
6. Requires a deadline (block height limit)

##### `remove_liquidity()`
#### `remove_liquidity()`

1. Allows removing liquidity from the pool
1. If the asset pair of the pool is set
Expand All @@ -102,14 +101,14 @@ This sub-section details what a user is able to do, e.g., click a button and "x,
4. Requires the minimum amounts of both assets to receive after burning
5. Requires a deadline (block height limit)

##### `withdraw()`
#### `withdraw()`

1. Allows withdrawing previously deposited assets without using them to add liquidity
1. If the asset pair of the pool is set
2. If the deposited amount of the asset is sufficient
3. Requires an amount of either asset to withdraw

##### `swap_exact_input()`
#### `swap_exact_input()`

1. Allows selling an exact amount of an asset for the other asset
1. If the asset pair of the pool is set
Expand All @@ -122,7 +121,7 @@ This sub-section details what a user is able to do, e.g., click a button and "x,
7. Requires a deadline (block height limit)


##### `swap_exact_output()`
#### `swap_exact_output()`

1. Allows selling an asset for an exact amount of the other asset
1. If the asset pair of the pool is set
Expand All @@ -135,41 +134,65 @@ This sub-section details what a user is able to do, e.g., click a button and "x,
> **NOTE** This is a safety mechanism against excessive slippage. The [`preview_swap_exact_output()`](#preview_swap_exact_output) function can be used to calculate a reasonable maximum input amount.
8. Requires a deadline (block height limit)

#### Previews
### Previews

##### `preview_add_liquidity()`
#### `preview_add_liquidity()`

1. Returns the amount of the other asset to input and the liquidity asset amount to receive after an add liquidity operation
1. If the asset pair of the pool is set
2. Requires the amount of an asset to input to [`add_liquidity`](#add_liquidity)
> **NOTE** If any liquidity in the contract already exists, than the amount of the other asset is calculated based on the ratio of the assets. Otherwise, the ratio is assumed to be 1.

##### `preview_swap_exact_input()`
#### `preview_swap_exact_input()`

1. Returns the minimum output amount to receive after a [`swap_exact_input`](#swap_exact_input) and whether the output asset reserves are sufficient for the swap
1. If the asset pair of the pool is set
2. Requires an exact amount of either asset to sell

##### `preview_swap_exact_output()`
#### `preview_swap_exact_output()`

1. Returns the maximum input amount for a [`swap_exact_output`](#swap_exact_output) and whether the input asset reserves are sufficient for the swap
1. If the asset pair of the pool is set
2. If the output asset reserves are sufficient for the swap
3. Requires an exact amount of either asset to buy

#### State Checks
### State Checks

##### `balance()`
#### `balance()`

1. Returns the asset balance of the sender in the contract
1. If the asset pair of the pool is set
2. Requires the asset identifier to return the balance for

##### `pool_info()`
#### `pool_info()`

1. Returns the pool info, i.e., the identifiers and amounts of assets and the liquidity pool asset amount
1. If the asset pair of the pool is set

## Sequence Diagram
## Scripts

### `atomic-add-liquidity`

1. Deposits pool assets and adds liquidity
1. If desired liquidity is more than 0
2. If [`deposit`](#deposit) and [`add_liquidity`](#add_liquidity) conditions are met

### `swap-exact-input`

1. Swaps assets along a route by specifying exact input for each swap
1. If the route has at least 2 assets
2. If the AMM has a pool for each subsequent asset pair in route
3. If the bought amount of the last asset is more than the optional minimum output amount
4. If [`swap_exact_input`](#swap_exact_input) conditions are met

### `swap-exact-output`

1. Swaps assets along a route by specifying exact output for each swap
1. If the route has at least 2 assets
3. If the AMM has a pool for each subsequent asset pair in route
3. If the sold amount of the first asset is less than the specified maximum input amount
4. If [`swap_exact_output`](#swap_exact_output) conditions are met

# Sequence Diagram

![AMM Sequence Diagram](.docs/amm-sequence-diagram.png)
Braqzen marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion AMM/project/contracts/AMM-contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ edition = "2021"
license = "Apache-2.0"

[dependencies]
fuels = { version = "0.33.0", features = ["fuel-core-lib"] }
fuels = { git = "https://github.com/FuelLabs/fuels-rs.git", features = ["fuel-core-lib"] }
supiket marked this conversation as resolved.
Show resolved Hide resolved
test-utils = { path = "../../test-utils" }
tokio = { version = "1.21.0", features = ["rt", "macros"] }

[[test]]
Expand Down
3 changes: 2 additions & 1 deletion AMM/project/contracts/AMM-contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ impl AMM for Contract {

let exchange_contract = abi(Exchange, pool.into());
let pool_info = exchange_contract.pool_info();
let pair_matches_exchange_pair = (pool_info.asset_a == asset_pair.0 && pool_info.asset_b == asset_pair.1) || (pool_info.asset_a == asset_pair.1 && pool_info.asset_b == asset_pair.0);
let pair = pool_info.reserves;
let pair_matches_exchange_pair = (pair.a.id == asset_pair.0 && pair.b.id == asset_pair.1) || (pair.a.id == asset_pair.1 && pair.b.id == asset_pair.0);

require(pair_matches_exchange_pair, InitError::PairDoesNotDefinePool);

Expand Down
Loading