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

feat: Add contract astroport-pair-xyk-sale-tax #381

Merged
merged 22 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0bc5b53
feat: copy xyk pair to new contract
apollo-sturdy Sep 12, 2023
12df1a0
feat: Implement sale tax
apollo-sturdy Sep 12, 2023
4704c33
test: Update tests to work with sale tax
apollo-sturdy Sep 12, 2023
e13e8ab
feat: Support tax on selling both pair assets
apollo-sturdy Oct 17, 2023
f8136da
feat: add tax_config_admin
apollo-sturdy Oct 17, 2023
a67792a
feat: Add migration from standard xyk
apollo-sturdy Oct 17, 2023
bcd3a6e
test: Add test for migrate
apollo-sturdy Oct 18, 2023
ec8e3dd
fix: Allow migrating from 1.3.0 and 1.3.1
apollo-sturdy Oct 18, 2023
277dcda
fix: Add migratemsg to schema
apollo-sturdy Oct 18, 2023
3131b44
chore: cargo update
apollo-sturdy Oct 18, 2023
2aaf02f
docs: Update readme
apollo-sturdy Oct 18, 2023
1be15c4
fix: Allow migrating from 1.5.0
apollo-sturdy Oct 18, 2023
b4484cf
refactor: Struct for return type of compute_swap
apollo-sturdy Oct 18, 2023
f928ac3
fix: Error whn not migrating from astroport-pair
apollo-sturdy Oct 25, 2023
26540eb
feat: Set cw2 data and add events on migration
apollo-sturdy Oct 25, 2023
b0fc7c0
fix: Change pairtype to xyk in instantiate
apollo-sturdy Oct 25, 2023
9e83085
feat: Change max tax rate to 50%
apollo-sturdy Oct 25, 2023
cfbfbf9
Revert "fix: Change pairtype to xyk in instantiate"
apollo-sturdy Jan 11, 2024
cc63d0a
chore: set xyk-sale-tax version to 1.6.0
apollo-sturdy Jan 11, 2024
d691b35
test: Add test migrating from 1.3.1
apollo-sturdy Jan 11, 2024
0912b30
chore: bump astroport package version to 3.9.0
apollo-sturdy Jan 12, 2024
87ba4c7
test: update to new balance mismatch error message
apollo-sturdy Jan 12, 2024
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
790 changes: 472 additions & 318 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"contracts/pair_concentrated",
# "contracts/pair_concentrated_inj", TODO: rewrite OB liquidity deployment
"contracts/pair_astro_xastro",
"contracts/pair_xyk_sale_tax",
"contracts/router",
"contracts/token",
"contracts/whitelist",
Expand Down
6 changes: 6 additions & 0 deletions contracts/pair_xyk_sale_tax/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
unit-test = "test --lib"
integration-test = "test --test integration"
schema = "run --example pair_schema"
11 changes: 11 additions & 0 deletions contracts/pair_xyk_sale_tax/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.rs]
indent_size = 4
46 changes: 46 additions & 0 deletions contracts/pair_xyk_sale_tax/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[package]
name = "astroport-pair-xyk-sale-tax"
version = "1.6.0"
authors = ["Astroport", "Sturdy"]
edition = "2021"
description = "The Astroport constant product pool contract implementation"
license = "MIT"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for quicker tests, cargo test --lib
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
library = []

[dependencies]
integer-sqrt = "0.1"
astroport = { path = "../../packages/astroport", default-features = false }
cw2 = "0.15"
cw20 = "0.15"
cosmwasm-std = "1.1"
cw-storage-plus = "0.15"
thiserror = { version = "1.0" }
protobuf = { version = "2", features = ["with-bytes"] }
cosmwasm-schema = "1.1"
cw-utils = "1.0.1"
astroport-pair = { path = "../pair", features = ["library"] }

[dev-dependencies]
astroport-token = { path = "../token" }
astroport-factory = { path = "../factory" }
proptest = "1.0"
prost = "0.11.5"
astroport-mocks = { path = "../../packages/astroport_mocks/" }
astroport-pair-1_3_1 = { package = "astroport-pair", version = "1.3.1", features = ["library"] }
test-case = "3.3.1"
303 changes: 303 additions & 0 deletions contracts/pair_xyk_sale_tax/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
# Astroport Constant Product Pair with Sale Tax

The constant product pool uses the widely known xy=k formula. More details around how the pool functions can be found [here](https://docs.astroport.fi/astroport/astroport/astro-pools/constant-product-pools).

This is a modified version of the standard Astroport XYK pair which adds a configurable sale tax. The tax can be added on each of the assets in the pair and is taken on the offered asset before calculating the return amount.

---

## Liquidity Providers

A user can provide liquidity to a constant product pool by calling `provide_liquidity`. Users can also withdraw liquidity by calling `withdraw_liquidity`.

Whenever liquidity is deposited into a pool, special tokens known as "liquidity tokens" are minted to the provider’s address, in proportion to how much liquidity they contributed to the pool. These tokens are a representation of a liquidity provider’s contribution to a pool. Whenever a trade occurs, the `lp_commission` is distributed pro-rata to all LPs in the pool at the moment of the trade. To receive the underlying liquidity back plus accrued LP fees, LPs must burn their liquidity tokens.

When providing liquidity from a smart contract, the most important thing to keep in mind is that the amount of tokens deposited into a pool and the amount of tokens withdrawn later from the pool will most likely not be the same. This is because of the way constant product pools work where, as the token prices in the pool change, so do the respective token amounts that a LP can withdraw.

As an example, let's say the global ratio between two tokens x:y is 10:2 (i.e. 1 x = 0.2 y), but the current ratio between the tokens in an Astroport pair is 5:2 (1 x = 0.4 y). Let's also say that someone may decide to LP in the x:y Astroport pool at the current 5:2 ratio. As the Astroport pool gets arbitraged to the global ratio, the amount of x & y tokens that the LP can withdraw changes because the total amounts of x & y tokens in the pool also change.

> Note that before executing the `provide_liqudity` operation, a user must allow the pool contract to take tokens from their wallet

### Slippage Tolerance for Providing Liquidity

If a user specifies a slippage tolerance when they provide liquidity in a constant product pool, the pool contract makes sure that the transaction goes through only if the pool price does not change more than tolerance.

As an example, let's say someone LPs in a pool and specifies a 1% slippage tolerance. The user LPs 200 UST and 1 `ASSET`. With a 1% slippage tolerance, `amountUSTMin` (the minimum amount of UST to LP) should be set to 198 UST, and `amountASSETMin` (the minimum amount of `ASSET` to LP) should be set to .99 `ASSET`. This means that, in a worst case scenario, liquidity will be added at a pool rate of 198 `ASSET`/1 UST or 202.02 UST/1 `ASSET` (200 UST + .99 `ASSET`). If the contract cannot add liquidity within these bounds (because the pool ratio changed more than the tolerance), the transaction will revert.

## Traders

### Slippage Tolerance for Swaps

Astroport has two options to protect traders against slippage during swaps:

1. Providing `max_spread`
The spread is calculated as the difference between the ask amount (using the constant pool price) before and after the swap operation. Once `max_spread` is set, it will be compared against the actual swap spread. In case the swap spread exceeds the provided max limit, the swap will fail.

Note that the spread is calculated before commission deduction in order to properly represent the pool's ratio change.

2. Providing `max_spread` + `belief_price`
If `belief_price` is provided in combination with `max_spread`, the pool will check the difference between the return amount (using `belief_price`) and the real pool price.

Please note that Astroport has the default value for the spread set to 0.5% and the max allowed spread set to 50%.

## InstantiateMsg

Initializes a new x\*y=k pair.

```json
{
"token_code_id": 123,
"factory_addr": "terra...",
"asset_infos": [
{
"token": {
"contract_addr": "terra..."
}
},
{
"native_token": {
"denom": "uusd"
}
}
],
"init_params": "<base64_encoded_json_string: optional binary serialised parameters for custom pool types>"
}
```

## ExecuteMsg

### `receive`

Withdraws liquidity or assets that were swapped to (ask assets in a swap operation).

```json
{
"receive": {
"sender": "terra...",
"amount": "123",
"msg": "<base64_encoded_json_string>"
}
}
```

### `provide_liquidity`

Provides liquidity by sending a user's native or token assets to the pool.

**NOTE**: you should increase your token allowance for the pool before providing liquidity!

1. Providing Liquidity Without Specifying Slippage Tolerance

```json
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra..."
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
"auto_stake": false,
"receiver": "terra..."
}
}
```

2. Providing Liquidity With Slippage Tolerance

```json
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra..."
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
"slippage_tolerance": "0.01",
"auto_stake": false,
"receiver": "terra..."
}
}
```

### `withdraw_liquidity`

Burn LP tokens and withdraw liquidity from a pool. This call must be sent to a LP token contract associated with the pool from which you want to withdraw liquidity from.

```json
{
"withdraw_liquidity": {}
}
```

### `swap`

Perform a swap. `offer_asset` is your source asset and `to` is the address that will receive the ask assets. All fields are optional except `offer_asset`.

NOTE: You should increase token allowance before swap.

```json
{
"swap": {
"offer_asset": {
"info": {
"native_token": {
"denom": "uluna"
}
},
"amount": "123"
},
"belief_price": "123",
"max_spread": "123",
"to": "terra..."
}
}
```

### `update_config`

The contract configuration cannot be updated.

```json
{
"update_config": {
"params": "<base64_encoded_json_string>"
}
}
```

## QueryMsg

All query messages are described below. A custom struct is defined for each query response.

### `pair`

Retrieve a pair's configuration (type, assets traded in it etc)

```json
{
"pair": {}
}
```

### `pool`

Returns the amount of tokens in the pool for all assets as well as the amount of LP tokens issued.

```json
{
"pool": {}
}
```

### `config`

Get the pair contract configuration.

```json
{
"config": {}
}
```

### `share`

Return the amount of assets someone would get from the pool if they were to burn a specific amount of LP tokens.

```json
{
"share": {
"amount": "123"
}
}
```

### `simulation`

Simulates a swap and returns the spread and commission amounts.

```json
{
"simulation": {
"offer_asset": {
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
}
}
```

### `reverse_simulation`

Reverse simulates a swap (specifies the ask instead of the offer) and returns the offer amount, spread and commission.

```json
{
"reverse_simulation": {
"ask_asset": {
"info": {
"token": {
"contract_addr": "terra..."
}
},
"amount": "1000000"
}
}
}
```

### `cumulative_prices`

Returns the cumulative prices for the assets in the pair.

```json
{
"cumulative_prices": {}
}
```

### `asset_balance_at`

Returns the balance of the specified asset that was in the pool just preceeding the moment of the specified block height creation. It will return None (null) if the balance was not tracked up to the specified block height.

```json
{
"asset_balance_at": {
"asset_info": {
"native_token": {
"denom": "stake"
}
},
"block_height": "12345678"
}
}
```
12 changes: 12 additions & 0 deletions contracts/pair_xyk_sale_tax/examples/pair_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use astroport::pair::{ExecuteMsg, InstantiateMsg, QueryMsg};
use astroport::pair_xyk_sale_tax::MigrateMsg;
use cosmwasm_schema::write_api;

fn main() {
write_api! {
instantiate: InstantiateMsg,
query: QueryMsg,
execute: ExecuteMsg,
migrate: MigrateMsg,
}
}
Loading
Loading