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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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}