Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

lp_test.gno

4.20 Kb · 113 lines
  1package amm
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/grc20/v0"
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9	"gno.land/r/nt/grc20reg/v0"
 10)
 11
 12// A third token, so a second pool can prove each one mints its own LP token.
 13var (
 14	tokCCC *grc20.Token
 15	ledCCC *grc20.PrivateLedger
 16	keyCCC string
 17)
 18
 19func init(cur realm) {
 20	tokCCC, ledCCC = grc20.NewToken("Test Gamma", "CCC", 6, 2, cur)
 21	keyCCC = grc20reg.Register(cross(cur), tokCCC, "")
 22}
 23
 24// TestLPPositionIsARealToken is the whole point of v1: the position exists
 25// outside this realm, as an ordinary registered GRC20.
 26func TestLPPositionIsARealToken(cur realm, t *testing.T) {
 27	reset()
 28	alice := testutils.TestAddress("lp-alice")
 29	fund(alice, 10_000_000)
 30	testing.SetRealm(testing.NewUserRealm(alice))
 31	minted := AddLiquidity(cross(cur), keyAAA, keyBBB, 1_000_000, 4_000_000)
 32
 33	// Readable by any realm that knows the key, without importing this one.
 34	lp := grc20reg.MustGet(LPToken(keyAAA, keyBBB))
 35	uassert.Equal(t, minted, lp.BalanceOf(alice))
 36	uassert.Equal(t, minted, lp.TotalSupply())
 37	uassert.Equal(t, minted, TotalShares(keyAAA, keyBBB))
 38	// The LP unit is token A at seed time, so it mirrors token A's decimals.
 39	uassert.Equal(t, tokAAA.GetDecimals(), lp.GetDecimals())
 40	uassert.Equal(t, "AMM LP AAA/BBB", lp.GetName())
 41}
 42
 43// TestLPIsTransferable: a position can change hands without touching the pool.
 44func TestLPIsTransferable(cur realm, t *testing.T) {
 45	reset()
 46	alice := testutils.TestAddress("xfer-alice")
 47	bob := testutils.TestAddress("xfer-bob")
 48	fund(alice, 10_000_000)
 49
 50	testing.SetRealm(testing.NewUserRealm(alice))
 51	AddLiquidity(cross(cur), keyAAA, keyBBB, 1_000_000, 4_000_000)
 52	TransferLP(cross(cur), keyAAA, keyBBB, bob, 500_000)
 53
 54	uassert.Equal(t, int64(500_000), SharesOf(keyAAA, keyBBB, alice))
 55	uassert.Equal(t, int64(500_000), SharesOf(keyAAA, keyBBB, bob))
 56
 57	// Bob exits on a position he was given, having never deposited anything.
 58	// In v0 this is not expressible at all.
 59	testing.SetRealm(testing.NewUserRealm(bob))
 60	gotA, gotB := RemoveLiquidity(cross(cur), keyAAA, keyBBB, 500_000)
 61	uassert.Equal(t, int64(500_000), gotA)
 62	uassert.Equal(t, int64(2_000_000), gotB)
 63	uassert.Equal(t, int64(500_000), tokAAA.BalanceOf(bob), "bob was never funded")
 64}
 65
 66// TestLPAllowance: the approve/transferFrom surface v1 gains, and the abort
 67// when it is spent past its limit.
 68func TestLPAllowance(cur realm, t *testing.T) {
 69	reset()
 70	alice := testutils.TestAddress("allow-alice")
 71	carol := testutils.TestAddress("allow-carol")
 72	fund(alice, 10_000_000)
 73
 74	testing.SetRealm(testing.NewUserRealm(alice))
 75	AddLiquidity(cross(cur), keyAAA, keyBBB, 1_000_000, 1_000_000)
 76	ApproveLP(cross(cur), keyAAA, keyBBB, carol, 300_000)
 77	uassert.Equal(t, int64(300_000), AllowanceLP(keyAAA, keyBBB, alice, carol))
 78
 79	testing.SetRealm(testing.NewUserRealm(carol))
 80	TransferFromLP(cross(cur), keyAAA, keyBBB, alice, carol, 300_000)
 81	uassert.Equal(t, int64(300_000), SharesOf(keyAAA, keyBBB, carol))
 82	uassert.Equal(t, int64(700_000), SharesOf(keyAAA, keyBBB, alice))
 83	uassert.Equal(t, int64(0), AllowanceLP(keyAAA, keyBBB, alice, carol))
 84
 85	uassert.AbortsContains(t, cur, "insufficient allowance", func() {
 86		TransferFromLP(cross(cur), keyAAA, keyBBB, alice, carol, 1)
 87	})
 88}
 89
 90// TestEachPoolMintsItsOwnLPToken: two pools, two distinct registered tokens.
 91func TestEachPoolMintsItsOwnLPToken(cur realm, t *testing.T) {
 92	reset()
 93	alice := testutils.TestAddress("two-alice")
 94	fund(alice, 10_000_000)
 95	ledCCC.Mint(alice, 10_000_000)
 96	ledCCC.Approve(alice, self(), 10_000_000)
 97
 98	testing.SetRealm(testing.NewUserRealm(alice))
 99	AddLiquidity(cross(cur), keyAAA, keyBBB, 1_000_000, 4_000_000)
100	AddLiquidity(cross(cur), keyAAA, keyCCC, 2_000_000, 2_000_000)
101
102	ab := LPToken(keyAAA, keyBBB)
103	ac := LPToken(keyAAA, keyCCC)
104	uassert.NotEqual(t, ab, ac, "one LP token per pool")
105	uassert.Equal(t, int64(1_000_000), grc20reg.MustGet(ab).TotalSupply())
106	uassert.Equal(t, int64(2_000_000), grc20reg.MustGet(ac).TotalSupply())
107	uassert.Equal(t, "AMM LP AAA/CCC", grc20reg.MustGet(ac).GetName())
108
109	// Moving one pool's LP leaves the other alone.
110	TransferLP(cross(cur), keyAAA, keyBBB, testutils.TestAddress("two-bob"), 400_000)
111	uassert.Equal(t, int64(600_000), SharesOf(keyAAA, keyBBB, alice))
112	uassert.Equal(t, int64(2_000_000), SharesOf(keyAAA, keyCCC, alice))
113}