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(smart-contracts): add stableswap support for provide liquidity #351

Merged
merged 52 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
84ae06b
feat(smart-contracts): add stableswap support for provide liquidity
nseguias May 6, 2024
4cb71f5
chore: please the lord clippy
nseguias May 6, 2024
c14fb19
feat(smart-contracts): make provide liquidity for stableswap generic …
nseguias May 7, 2024
0176c1a
chore(smart-contracts): please the lord clippy
nseguias May 7, 2024
9b00cc2
fix(smart-contracts): refactor to use generic n_coins using deposits.…
nseguias May 7, 2024
9fe2631
chore(smart-contracts): remvoe unnecessary comments
nseguias May 7, 2024
7f3d4e5
test(smart-contracts): add tests (including proptests) for pool manag…
nseguias May 23, 2024
249d0bc
feat(smart-contracts): test math for pool manager
nseguias May 23, 2024
106de06
feat(smart-contracts): address PR comments
nseguias May 27, 2024
93bfa2d
feat(smart-contracts): address PR comments
nseguias May 27, 2024
ef3f1ca
feat(smart-contracts): address PR comments
nseguias May 27, 2024
45c7cf6
fix(smart-contracts): update slippage tolerance to work with N coins …
nseguias May 28, 2024
0ea5afd
fix(smart-contracts): update slippage tolerance to work with N coins
nseguias May 28, 2024
045a8f1
chore: bump cosmwasm-* versions
kerber0x May 6, 2024
da16403
refactor: remove the temporary FillRewardsCoin msg from the whalelair…
kerber0x May 6, 2024
a4bbed0
refactor: abstract bank burn msg
kerber0x May 6, 2024
6a5522e
refactor: make epoch id u64 on epoch manager
kerber0x May 6, 2024
6c8ea5b
test: use the bonding-manager in pool-manager tests
kerber0x May 6, 2024
db23e50
chore: remove factory flags from token_factory package
kerber0x May 7, 2024
26472df
refactor: bonding-manager
kerber0x May 8, 2024
4a36492
test(bonding-manager): fix instantiate tests
kerber0x May 8, 2024
c364fc1
test(bonding-manager): fix update config tests
kerber0x May 8, 2024
1f3acee
test: fix bond tests
kerber0x May 9, 2024
87aaccb
refactor: update types, change weight calculation from timestamp to e…
kerber0x May 9, 2024
eaaaa4f
refactor: rename bonding-manager.epochs to reward buckets
kerber0x May 9, 2024
7e4b523
chore: start point before major remake of the bonding mechanism
kerber0x May 13, 2024
1f5d722
refactor: move functions to proper folders
kerber0x May 13, 2024
f1b18fb
refactor: using upcoming_reward_bucket when filling rewards
kerber0x May 13, 2024
5de11ef
chore: add last_claimed_epoch when bonding
kerber0x May 14, 2024
76aa0f7
chore: add rewards query
kerber0x May 15, 2024
ff9c23f
test: enable rewards test
kerber0x May 15, 2024
bcb7676
test: add more test coverage, to helpers and bonding
kerber0x May 16, 2024
0e8c4e5
test: add unbond and withdraw tests
kerber0x May 16, 2024
4b8f840
chore: fix broken tests
kerber0x May 16, 2024
9b124e3
refactor: move a few functiosn to helpers.rs
kerber0x May 17, 2024
55990d1
refactor: cleanup state
kerber0x May 17, 2024
01cf973
chore: final refactor
kerber0x May 17, 2024
64176dd
test: use test_case for extract_pool_identifier unit test
kerber0x May 20, 2024
35aaa12
docs: add readme to bonding-manager
kerber0x May 20, 2024
e26f79d
chore: fix PR comments
kerber0x May 20, 2024
39b3bc7
docs: tweak v2 architecture diagram
kerber0x May 20, 2024
ae0591c
docs(epoch-manager): add readme to epoch manager
kerber0x May 20, 2024
52bed91
docs(epoch-manager): add epoch details and hook mechanismm diagram
kerber0x May 21, 2024
15896a2
docs(incentive-manager): add readme to incentive manager
kerber0x May 21, 2024
daed937
docs(vault-manager): add readme for vault manager
kerber0x May 21, 2024
b7ea839
docs(bonding-manager): add diagram of reward distribution (#359)
kerber0x May 21, 2024
2fda9be
docs(pool-manager): add readme to pool manager (#356)
kerber0x May 21, 2024
78ca31f
docs(epopoch-manager): add missing docummentation to structs and enum…
kerber0x May 23, 2024
0975046
fix: Rework all v2 contracts to use bonding-manager not whale-lair (#…
0xFable May 24, 2024
8302636
chore(repo): resolving dependency & package conflicts
nseguias May 31, 2024
750b02a
test: fix min liquidity amount check for stableswap
kerber0x Jun 4, 2024
2f40957
chore: merge branch 'release/v2_contracts' into feat/stableswap-case-…
kerber0x Jun 4, 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
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/liquidity_hub/incentive-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ epoch-manager.workspace = true
whale-lair.workspace = true
anyhow.workspace = true
bonding-manager.workspace = true
pool-manager.workspace = true
pool-manager.workspace = true
3 changes: 3 additions & 0 deletions contracts/liquidity_hub/pool-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ incentive-manager.workspace = true
epoch-manager.workspace = true
white-whale-testing.workspace = true
bonding-manager.workspace = true
proptest = "1.0.0"
rand = "0.8.4"
stable-swap-sim = { path = "./sim", version = "^0.1" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 55857276de2241e3d09d36aba47854e0017db66f6c5a61e306b38ad0d3b8aeeb # shrinks to amp_factor = 1, initial_user_token_a_amount = 10000000, initial_user_token_b_amount = 10000000
cc 33456e9a9f11bed69ac5171155ce7a64f73f912fcbfede19046989302d1b2da9 # shrinks to amp_factor = 10, deposit_amount_a = 0, deposit_amount_b = 0, deposit_amount_c = 0, swap_token_a_amount = 0, swap_token_b_amount = 0, swap_token_c_amount = 1, pool_token_supply = 0
cc 75c3b0922c450b034b92dc8c2ea87edff47c90bbede702d84c9fd9c672e2f31f # shrinks to amp_factor = 141, deposit_amount_a = 308442737939502983046195411808336, deposit_amount_b = 0, deposit_amount_c = 0, swap_token_a_amount = 870112623450347049437652954298478, swap_token_b_amount = 501497230776538877048085549853566, swap_token_c_amount = 24063806364666791266594852039507, pool_token_supply = 2
12 changes: 12 additions & 0 deletions contracts/liquidity_hub/pool-manager/sim/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "stable-swap-sim"
version = "0.1.0"
description = "Simulations of the StableSwap invariant compared to Curve's reference implementation."
authors = ["Paul Stelzig [email protected]>"]
edition = "2021"

[lib]
name = "sim"

[dependencies]
pyo3 = { version = "0.17.3", features = ["auto-initialize"] }
172 changes: 172 additions & 0 deletions contracts/liquidity_hub/pool-manager/sim/simulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Source from: https://github.com/curvefi/curve-contract/blob/master/tests/simulation.py

class Curve:

"""
Python model of Curve pool math.
"""

def __init__(self, A, D, n, p=None, tokens=None):
"""
A: Amplification coefficient
D: Total deposit size
n: number of currencies
p: target prices
"""
self.A = A # actually A * n ** (n - 1) because it's an invariant
self.n = n
self.fee = 10 ** 7
if p:
self.p = p
else:
self.p = [10 ** 18] * n
if isinstance(D, list):
self.x = D
else:
self.x = [D // n * 10 ** 18 // _p for _p in self.p]
self.tokens = tokens

def xp(self):
return [x * p // 10 ** 18 for x, p in zip(self.x, self.p)]

def D(self):
"""
D invariant calculation in non-overflowing integer operations
iteratively

A * sum(x_i) * n**n + D = A * D * n**n + D**(n+1) / (n**n * prod(x_i))

Converging solution:
D[j+1] = (A * n**n * sum(x_i) - D[j]**(n+1) / (n**n prod(x_i))) / (A * n**n - 1)
"""
Dprev = 0
xp = self.xp()
S = sum(xp)
D = S
Ann = self.A * self.n
while abs(D - Dprev) > 1:
D_P = D
for x in xp:
D_P = D_P * D // (self.n * x)
Dprev = D
D = (Ann * S + D_P * self.n) * D // ((Ann - 1) * D + (self.n + 1) * D_P)

return D

def y(self, i, j, x):
"""
Calculate x[j] if one makes x[i] = x

Done by solving quadratic equation iteratively.
x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
x_1**2 + b*x_1 = c

x_1 = (x_1**2 + c) / (2*x_1 + b)
"""
D = self.D()
xx = self.xp()
xx[i] = x # x is quantity of underlying asset brought to 1e18 precision
xx = [xx[k] for k in range(self.n) if k != j]
Ann = self.A * self.n
c = D
for y in xx:
c = c * D // (y * self.n)
c = c * D // (self.n * Ann)
b = sum(xx) + D // Ann - D
y_prev = 0
y = D
while abs(y - y_prev) > 1:
y_prev = y
y = (y ** 2 + c) // (2 * y + b)
return y # the result is in underlying units too

def y_D(self, i, _D):
"""
Calculate x[j] if one makes x[i] = x

Done by solving quadratic equation iteratively.
x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
x_1**2 + b*x_1 = c

x_1 = (x_1**2 + c) / (2*x_1 + b)
"""
xx = self.xp()
xx = [xx[k] for k in range(self.n) if k != i]
S = sum(xx)
Ann = self.A * self.n
c = _D
for y in xx:
c = c * _D // (y * self.n)
c = c * _D // (self.n * Ann)
b = S + _D // Ann
y_prev = 0
y = _D
while abs(y - y_prev) > 1:
y_prev = y
y = (y ** 2 + c) // (2 * y + b - _D)
return y # the result is in underlying units too

def dy(self, i, j, dx):
# dx and dy are in underlying units
xp = self.xp()
return xp[j] - self.y(i, j, xp[i] + dx)

def exchange(self, i, j, dx):
xp = self.xp()
x = xp[i] + dx
y = self.y(i, j, x)
dy = xp[j] - y
fee = dy * self.fee // 10 ** 10
assert dy > 0
self.x[i] = x * 10 ** 18 // self.p[i]
self.x[j] = (y + fee) * 10 ** 18 // self.p[j]
return dy - fee

def remove_liquidity_imbalance(self, amounts):
_fee = self.fee * self.n // (4 * (self.n - 1))

old_balances = self.x
new_balances = self.x[:]
D0 = self.D()
for i in range(self.n):
new_balances[i] -= amounts[i]
self.x = new_balances
D1 = self.D()
self.x = old_balances
fees = [0] * self.n
for i in range(self.n):
ideal_balance = D1 * old_balances[i] // D0
difference = abs(ideal_balance - new_balances[i])
fees[i] = _fee * difference // 10 ** 10
new_balances[i] -= fees[i]
self.x = new_balances
D2 = self.D()
self.x = old_balances

token_amount = (D0 - D2) * self.tokens // D0

return token_amount

def calc_withdraw_one_coin(self, token_amount, i):
xp = self.xp()
xp_reduced = list(xp)

D0 = self.D()
D1 = D0 - token_amount * D0 // self.tokens
new_y = self.y_D(i, D1)

fee = self.fee * self.n // (4 * (self.n - 1))
for j in range(self.n):
dx_expected = 0
if j == i:
dx_expected = xp[j] * D1 // D0 - new_y
else:
dx_expected = xp[j] - xp[j] * D1 // D0
xp_reduced[j] -= fee * dx_expected // 10 ** 10

self.x = [x * 10 ** 18 // p for x, p in zip(xp_reduced, self.p)]
dy = xp_reduced[i] - self.y_D(i, D1) - 1 # Withdraw less to account for rounding errors
self.x = [x * 10 ** 18 // p for x, p in zip(xp, self.p)]
dy_0 = xp[i] - new_y

return dy, dy_0 - dy
Loading
Loading