From edfb2965453dd6c29e89abb40a4c92e957258f5b Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 19:48:28 +0900 Subject: [PATCH 01/30] GSW-1838 refactor: use grc20reg - use gno's grc20reg realm to support dynamic token transfer in pool --- pool/pool.gno | 53 ++--- .../__TEST_0_INIT_TOKEN_REGISTER_test.gnoA | 183 ------------------ ..._TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA | 6 + pool/utils.gno | 9 + 4 files changed, 45 insertions(+), 206 deletions(-) delete mode 100644 pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA diff --git a/pool/pool.gno b/pool/pool.gno index 1ab2b869..0ce792a6 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -145,12 +145,18 @@ func Collect( // Smallest of three: amount0Requested, position.tokensOwed0, pool.balances.token0 amount0Req := u256.MustFromDecimal(amount0Requested) amount0, position.tokensOwed0, pool.balances.token0 = collectToken(amount0Req, position.tokensOwed0, pool.balances.token0) - transferByRegisterCall(pool.token0Path, recipient, amount0.Uint64()) + token0 := common.GetToken(pool.token0Path) + checkTransferError(token0.Transfer(recipient, amount0.Uint64())) // Smallest of three: amount0Requested, position.tokensOwed0, pool.balances.token0 amount1Req := u256.MustFromDecimal(amount1Requested) amount1, position.tokensOwed1, pool.balances.token1 = collectToken(amount1Req, position.tokensOwed1, pool.balances.token1) - transferByRegisterCall(pool.token1Path, recipient, amount1.Uint64()) + + // Update state first then transfer + position.tokensOwed1 = new(u256.Uint).Sub(position.tokensOwed1, amount1) + pool.balances.token1 = new(u256.Uint).Sub(pool.balances.token1, amount1) + token1 := common.GetToken(pool.token1Path) + checkTransferError(token1.Transfer(recipient, amount1.Uint64())) pool.positions[positionKey] = position @@ -175,15 +181,15 @@ func collectToken( // SwapResult encapsulates all state changes that occur as a result of a swap // This type ensure all state transitions are atomic and can be applied at once. type SwapResult struct { - Amount0 *i256.Int - Amount1 *i256.Int - NewSqrtPrice *u256.Uint - NewTick int32 - NewLiquidity *u256.Uint - NewProtocolFees ProtocolFees + Amount0 *i256.Int + Amount1 *i256.Int + NewSqrtPrice *u256.Uint + NewTick int32 + NewLiquidity *u256.Uint + NewProtocolFees ProtocolFees FeeGrowthGlobal0X128 *u256.Uint FeeGrowthGlobal1X128 *u256.Uint - SwapFee *u256.Uint + SwapFee *u256.Uint } // SwapComputation encapsulates pure computation logic for swap @@ -294,10 +300,11 @@ func Swap( // The function follows these state transitions: // 1. Initial State: Provided by `SwapComputation.InitialState` // 2. Stepping State: For each step: -// - Compute next tick and price target -// - Calculate amounts and fees -// - Update state (remaining amount, fees, liquidity) -// - Handle tick transitions if necessary +// - Compute next tick and price target +// - Calculate amounts and fees +// - Update state (remaining amount, fees, liquidity) +// - Handle tick transitions if necessary +// // 3. Final State: Aggregated in SwapResult // // The computation continues until either: @@ -309,7 +316,6 @@ func computeSwap(pool *Pool, comp SwapComputation) (*SwapResult, error) { state := comp.InitialState swapFee := u256.Zero() - var newFee *u256.Uint var err error @@ -342,7 +348,7 @@ func computeSwap(pool *Pool, comp SwapComputation) (*SwapResult, error) { }, FeeGrowthGlobal0X128: pool.feeGrowthGlobal0X128, FeeGrowthGlobal1X128: pool.feeGrowthGlobal1X128, - SwapFee: swapFee, + SwapFee: swapFee, } // Update protocol fees if necessary @@ -377,6 +383,7 @@ func applySwapResult(pool *Pool, result *SwapResult) { // For zeroForOne (selling token0): // - Price limit must be below current price // - Price limit must be above MIN_SQRT_RATIO +// // For !zeroForOne (selling token1): // - Price limit must be above current price // - Price limit must be below MAX_SQRT_RATIO @@ -562,6 +569,7 @@ func computeAmounts(state SwapState, sqrtRatioTargetX96 *u256.Uint, pool *Pool, // For exact input swaps: // - Decrements remaining input amount by (amountIn + feeAmount) // - Decrements calculated amount by amountOut +// // For exact output swaps: // - Increments remaining output amount by amountOut // - Increments calculated amount by (amountIn + feeAmount) @@ -814,8 +822,11 @@ func collectProtocol( uAmount0 := amount0.Uint64() uAmount1 := amount1.Uint64() - transferByRegisterCall(pool.token0Path, recipient, uAmount0) - transferByRegisterCall(pool.token1Path, recipient, uAmount1) + token0 := common.GetToken(pool.token0Path) + checkTransferError(token0.Transfer(recipient, uAmount0)) + + token1 := common.GetToken(pool.token1Path) + checkTransferError(token1.Transfer(recipient, uAmount1)) return amount0.ToString(), amount1.ToString() } @@ -943,12 +954,8 @@ func (pool *Pool) transferFromAndVerify( panic(err) } - // try sending - // will panic if following conditions are met: - // - POOL does not have enough approved amount - // - from does not have enough balance - // - token is not registered - transferFromByRegisterCall(tokenPath, from, to, amountUint64) + token := common.GetToken(tokenPath) + checkTransferError(token.TransferFrom(from, to, amountUint64)) // update pool balances if isToken0 { diff --git a/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA b/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA deleted file mode 100644 index 6702bd67..00000000 --- a/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA +++ /dev/null @@ -1,183 +0,0 @@ -package pool - -import ( - "std" - "testing" - - "gno.land/p/demo/testutils" - "gno.land/p/demo/uassert" - - "gno.land/r/onbloc/foo" - - "gno.land/r/onbloc/bar" - - "gno.land/r/onbloc/baz" - - "gno.land/r/onbloc/qux" - - "gno.land/r/demo/wugnot" - - "gno.land/r/onbloc/obl" - - "gno.land/r/gnoswap/v1/gns" - - "gno.land/r/gnoswap/v1/consts" - - pusers "gno.land/p/demo/users" -) - -type FooToken struct{} - -func (FooToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return foo.Transfer -} -func (FooToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return foo.TransferFrom -} -func (FooToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return foo.BalanceOf -} -func (FooToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return foo.Approve -} - -type BarToken struct{} - -func (BarToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return bar.Transfer -} -func (BarToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return bar.TransferFrom -} -func (BarToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return bar.BalanceOf -} -func (BarToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return bar.Approve -} - -type BazToken struct{} - -func (BazToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return baz.Transfer -} -func (BazToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return baz.TransferFrom -} -func (BazToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return baz.BalanceOf -} -func (BazToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return baz.Approve -} - -type QuxToken struct{} - -func (QuxToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return qux.Transfer -} -func (QuxToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return qux.TransferFrom -} -func (QuxToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return qux.BalanceOf -} -func (QuxToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return qux.Approve -} - -type WugnotToken struct{} - -func (WugnotToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return wugnot.Transfer -} -func (WugnotToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return wugnot.TransferFrom -} -func (WugnotToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return wugnot.BalanceOf -} -func (WugnotToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return wugnot.Approve -} - -type OBLToken struct{} - -func (OBLToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return obl.Transfer -} -func (OBLToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return obl.TransferFrom -} -func (OBLToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return obl.BalanceOf -} -func (OBLToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return obl.Approve -} - -type GNSToken struct{} - -func (GNSToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return gns.Transfer -} - -func (GNSToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return gns.TransferFrom -} - -func (GNSToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return gns.BalanceOf -} - -func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return gns.Approve -} - -func init() { - std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) -} - -func TestGetRegisteredTokens(t *testing.T) { - uassert.Equal(t, len(GetRegisteredTokens()), 7) -} - -func TestRegisterGRC20Interface(t *testing.T) { - uassert.PanicsWithMessage(t, - `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__RegisterGRC20Interface() || only register(g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5) can register token, called from g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm`, - func() { - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - }, - ) -} - -func TestUnregisterGRC20Interface(t *testing.T) { - dummy := testutils.TestAddress("dummy") - std.TestSetRealm(std.NewUserRealm(dummy)) - - uassert.PanicsWithMessage(t, - `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__UnregisterGRC20Interface() || unauthorized address(g1v36k6mteta047h6lta047h6lta047h6lz7gmv8) to unregister`, - func() { - UnregisterGRC20Interface("gno.land/r/onbloc/bar") - }, - ) - - uassert.Equal(t, len(GetRegisteredTokens()), 7) - - std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - UnregisterGRC20Interface("gno.land/r/onbloc/bar") - uassert.Equal(t, len(GetRegisteredTokens()), 6) - - // re-register to avoid panic in other tests - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - - std.TestSetRealm(adminRealm) -} diff --git a/pool/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA b/pool/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA index 4b6ba043..e92df972 100644 --- a/pool/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA +++ b/pool/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA @@ -3,6 +3,7 @@ package pool import ( "std" + "gno.land/r/gnoswap/v1/common" "gno.land/r/gnoswap/v1/consts" ) @@ -43,3 +44,8 @@ func ugnotBalanceOf(addr std.Address) uint64 { return uint64(coins.AmountOf("ugnot")) } + +func balanceOfByRegisterCall(tokenPath string, caller std.Address) uint64 { + token := common.GetToken(tokenPath) + return token.BalanceOf(caller) +} diff --git a/pool/utils.gno b/pool/utils.gno index 0ad4f4e6..b8d627a9 100644 --- a/pool/utils.gno +++ b/pool/utils.gno @@ -34,3 +34,12 @@ func getPrev() (string, string) { prev := std.PrevRealm() return prev.Addr().String(), prev.PkgPath() } + +func checkTransferError(err error) { + if err != nil { + panic(addDetailToError( + errTransferFailed, + err.Error(), + )) + } +} From 0411dd187e007119368d60ef8adfa4009d24eb40 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 17:16:50 +0900 Subject: [PATCH 02/30] GSW-1838 feat: grc20reg - replace previous token_register to latest grc20reg --- .../grc20reg/approve_and_transferfrom.txtar | 53 +++++++++++++ __local/grc20_tokens/grc20reg/gno.mod | 9 +++ __local/grc20_tokens/grc20reg/grc20reg.gno | 76 +++++++++++++++++++ .../grc20_tokens/grc20reg/grc20reg_test.gno | 59 ++++++++++++++ __local/grc20_tokens/onbloc/bar/bar.gno | 9 ++- __local/grc20_tokens/onbloc/bar/gno.mod | 1 + __local/grc20_tokens/onbloc/baz/baz.gno | 9 ++- __local/grc20_tokens/onbloc/baz/gno.mod | 1 + __local/grc20_tokens/onbloc/foo/foo.gno | 9 ++- __local/grc20_tokens/onbloc/foo/gno.mod | 1 + __local/grc20_tokens/onbloc/obl/gno.mod | 1 + __local/grc20_tokens/onbloc/obl/obl.gno | 9 ++- __local/grc20_tokens/onbloc/qux/gno.mod | 1 + __local/grc20_tokens/onbloc/qux/qux.gno | 9 ++- __local/grc20_tokens/onbloc/usdc/gno.mod | 1 + __local/grc20_tokens/onbloc/usdc/usdc.gno | 9 ++- _deploy/r/gnoswap/gns/gno.mod | 1 + _deploy/r/gnoswap/gns/gns.gno | 8 +- 18 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 __local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar create mode 100644 __local/grc20_tokens/grc20reg/gno.mod create mode 100644 __local/grc20_tokens/grc20reg/grc20reg.gno create mode 100644 __local/grc20_tokens/grc20reg/grc20reg_test.gno diff --git a/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar b/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar new file mode 100644 index 00000000..03b160b9 --- /dev/null +++ b/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar @@ -0,0 +1,53 @@ +loadpkg gno.land/p/demo/users + +loadpkg gno.land/r/demo/foo20 +loadpkg gno.land/r/demo/grc20reg + +loadpkg gno.land/r/demo/echo $WORK/echo + +## start a new node +gnoland start + +## faucet +# gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Faucet -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 + +## print reg addr +gnokey maketx call -pkgpath gno.land/r/demo/reg -func RelamAddr -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 +stdout 'g19tlskvga928es8ug2empargp0teul03apzjud9' + +## approve +gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Approve -args 'g19tlskvga928es8ug2empargp0teul03apzjud9' -args '100' -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 + +## transfer from +gnokey maketx call -pkgpath gno.land/r/demo/reg -func TransferFromWithReg -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 +stdout '' + +-- reg/reg.gno -- +package reg + +import ( + "std" + + "gno.land/r/demo/grc20reg" +) + +func RelamAddr() string { + addr := std.CurrentRealm().Addr().String() + return addr +} + +func TransferFromWithReg() { + caller := std.PrevRealm().Addr() + curr := std.CurrentRealm().Addr() + + + // using import + // foo20.TransferFrom(uCaller, uCurr, uint64(100)) + + // using grc20reg + fooTokenGetter := grc20reg.Get("gno.land/r/demo/foo20") + fooToken := fooTokenGetter() + userTeller := fooToken.CallerTeller() + + userTeller.TransferFrom(caller, curr, uint64(100)) +} \ No newline at end of file diff --git a/__local/grc20_tokens/grc20reg/gno.mod b/__local/grc20_tokens/grc20reg/gno.mod new file mode 100644 index 00000000..450e21be --- /dev/null +++ b/__local/grc20_tokens/grc20reg/gno.mod @@ -0,0 +1,9 @@ +module gno.land/r/gnoswap/v1/grc20reg + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/fqname v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest +) \ No newline at end of file diff --git a/__local/grc20_tokens/grc20reg/grc20reg.gno b/__local/grc20_tokens/grc20reg/grc20reg.gno new file mode 100644 index 00000000..ff46ec94 --- /dev/null +++ b/__local/grc20_tokens/grc20reg/grc20reg.gno @@ -0,0 +1,76 @@ +package grc20reg + +import ( + "std" + + "gno.land/p/demo/avl" + "gno.land/p/demo/fqname" + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/ufmt" +) + +var registry = avl.NewTree() // rlmPath[.slug] -> TokenGetter (slug is optional) + +func Register(tokenGetter grc20.TokenGetter, slug string) { + rlmPath := std.PrevRealm().PkgPath() + key := fqname.Construct(rlmPath, slug) + registry.Set(key, tokenGetter) + std.Emit( + registerEvent, + "pkgpath", rlmPath, + "slug", slug, + ) +} + +func Get(key string) grc20.TokenGetter { + tokenGetter, ok := registry.Get(key) + if !ok { + return nil + } + return tokenGetter.(grc20.TokenGetter) +} + +func MustGet(key string) grc20.TokenGetter { + tokenGetter := Get(key) + if tokenGetter == nil { + panic("unknown token: " + key) + } + return tokenGetter +} + +func Render(path string) string { + switch { + case path == "": // home + // TODO: add pagination + s := "" + count := 0 + registry.Iterate("", "", func(key string, tokenI interface{}) bool { + count++ + tokenGetter := tokenI.(grc20.TokenGetter) + token := tokenGetter() + rlmPath, slug := fqname.Parse(key) + rlmLink := fqname.RenderLink(rlmPath, slug) + infoLink := "/r/demo/grc20reg:" + key + s += ufmt.Sprintf("- **%s** - %s - [info](%s)\n", token.GetName(), rlmLink, infoLink) + return false + }) + if count == 0 { + return "No registered token." + } + return s + default: // specific token + key := path + tokenGetter := MustGet(key) + token := tokenGetter() + rlmPath, slug := fqname.Parse(key) + rlmLink := fqname.RenderLink(rlmPath, slug) + s := ufmt.Sprintf("# %s\n", token.GetName()) + s += ufmt.Sprintf("- symbol: **%s**\n", token.GetSymbol()) + s += ufmt.Sprintf("- realm: %s\n", rlmLink) + s += ufmt.Sprintf("- decimals: %d\n", token.GetDecimals()) + s += ufmt.Sprintf("- total supply: %d\n", token.TotalSupply()) + return s + } +} + +const registerEvent = "register" diff --git a/__local/grc20_tokens/grc20reg/grc20reg_test.gno b/__local/grc20_tokens/grc20reg/grc20reg_test.gno new file mode 100644 index 00000000..c93365ff --- /dev/null +++ b/__local/grc20_tokens/grc20reg/grc20reg_test.gno @@ -0,0 +1,59 @@ +package grc20reg + +import ( + "std" + "strings" + "testing" + + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/urequire" +) + +func TestRegistry(t *testing.T) { + std.TestSetRealm(std.NewCodeRealm("gno.land/r/demo/foo")) + realmAddr := std.CurrentRealm().PkgPath() + token, ledger := grc20.NewToken("TestToken", "TST", 4) + ledger.Mint(std.CurrentRealm().Addr(), 1234567) + tokenGetter := func() *grc20.Token { return token } + // register + Register(tokenGetter, "") + regTokenGetter := Get(realmAddr) + regToken := regTokenGetter() + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo) +` + got := Render("") + urequire.True(t, strings.Contains(got, expected)) + // 404 + invalidToken := Get("0xdeadbeef") + urequire.True(t, invalidToken == nil) + + // register with a slug + Register(tokenGetter, "mySlug") + regTokenGetter = Get(realmAddr + ".mySlug") + regToken = regTokenGetter() + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + // override + Register(tokenGetter, "") + regTokenGetter = Get(realmAddr + "") + regToken = regTokenGetter() + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + got = Render("") + urequire.True(t, strings.Contains(got, `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo)`)) + urequire.True(t, strings.Contains(got, `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).mySlug - [info](/r/demo/grc20reg:gno.land/r/demo/foo.mySlug)`)) + + expected = `# TestToken +- symbol: **TST** +- realm: [gno.land/r/demo/foo](/r/demo/foo).mySlug +- decimals: 4 +- total supply: 1234567 +` + got = Render("gno.land/r/demo/foo.mySlug") + urequire.Equal(t, expected, got) +} diff --git a/__local/grc20_tokens/onbloc/bar/bar.gno b/__local/grc20_tokens/onbloc/bar/bar.gno index c759395b..0be389fd 100644 --- a/__local/grc20_tokens/onbloc/bar/bar.gno +++ b/__local/grc20_tokens/onbloc/bar/bar.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Bar", "BAR", 6) + Token, ledger = grc20.NewToken("Bar", "BAR", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/__local/grc20_tokens/onbloc/bar/gno.mod b/__local/grc20_tokens/onbloc/bar/gno.mod index 8ed87d51..4e18b267 100644 --- a/__local/grc20_tokens/onbloc/bar/gno.mod +++ b/__local/grc20_tokens/onbloc/bar/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/baz/baz.gno b/__local/grc20_tokens/onbloc/baz/baz.gno index ad003225..d40f18a7 100644 --- a/__local/grc20_tokens/onbloc/baz/baz.gno +++ b/__local/grc20_tokens/onbloc/baz/baz.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Baz", "BAZ", 6) + Token, ledger = grc20.NewToken("Baz", "BAZ", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/__local/grc20_tokens/onbloc/baz/gno.mod b/__local/grc20_tokens/onbloc/baz/gno.mod index 6d1b8cd2..05230b44 100644 --- a/__local/grc20_tokens/onbloc/baz/gno.mod +++ b/__local/grc20_tokens/onbloc/baz/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/foo/foo.gno b/__local/grc20_tokens/onbloc/foo/foo.gno index 54451f3d..87dcbe32 100644 --- a/__local/grc20_tokens/onbloc/foo/foo.gno +++ b/__local/grc20_tokens/onbloc/foo/foo.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Foo", "FOO", 6) + Token, ledger = grc20.NewToken("Foo", "FOO", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/__local/grc20_tokens/onbloc/foo/gno.mod b/__local/grc20_tokens/onbloc/foo/gno.mod index bdd7de69..42e302af 100644 --- a/__local/grc20_tokens/onbloc/foo/gno.mod +++ b/__local/grc20_tokens/onbloc/foo/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/obl/gno.mod b/__local/grc20_tokens/onbloc/obl/gno.mod index a45fb79b..ffdeb5df 100644 --- a/__local/grc20_tokens/onbloc/obl/gno.mod +++ b/__local/grc20_tokens/onbloc/obl/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/obl/obl.gno b/__local/grc20_tokens/onbloc/obl/obl.gno index 890debb6..0815952c 100644 --- a/__local/grc20_tokens/onbloc/obl/obl.gno +++ b/__local/grc20_tokens/onbloc/obl/obl.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Obl", "OBL", 6) + Token, ledger = grc20.NewToken("Obl", "OBL", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/__local/grc20_tokens/onbloc/qux/gno.mod b/__local/grc20_tokens/onbloc/qux/gno.mod index 8e74cede..1528a033 100644 --- a/__local/grc20_tokens/onbloc/qux/gno.mod +++ b/__local/grc20_tokens/onbloc/qux/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/qux/qux.gno b/__local/grc20_tokens/onbloc/qux/qux.gno index 49585a9c..747ce978 100644 --- a/__local/grc20_tokens/onbloc/qux/qux.gno +++ b/__local/grc20_tokens/onbloc/qux/qux.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Qux", "QUX", 6) + Token, ledger = grc20.NewToken("Qux", "QUX", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/__local/grc20_tokens/onbloc/usdc/gno.mod b/__local/grc20_tokens/onbloc/usdc/gno.mod index 25836f4d..13d6b5cb 100644 --- a/__local/grc20_tokens/onbloc/usdc/gno.mod +++ b/__local/grc20_tokens/onbloc/usdc/gno.mod @@ -6,4 +6,5 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/__local/grc20_tokens/onbloc/usdc/usdc.gno b/__local/grc20_tokens/onbloc/usdc/usdc.gno index cd1db0df..9477bf0b 100644 --- a/__local/grc20_tokens/onbloc/usdc/usdc.gno +++ b/__local/grc20_tokens/onbloc/usdc/usdc.gno @@ -7,19 +7,24 @@ import ( "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) var ( admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Usd Coin", "USDC", 6) + Token, ledger = grc20.NewToken("Usd Coin", "USDC", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) + + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") } func TotalSupply() uint64 { return token.TotalSupply() } diff --git a/_deploy/r/gnoswap/gns/gno.mod b/_deploy/r/gnoswap/gns/gno.mod index 7963234e..8c541067 100644 --- a/_deploy/r/gnoswap/gns/gno.mod +++ b/_deploy/r/gnoswap/gns/gno.mod @@ -7,6 +7,7 @@ require ( gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest gno.land/r/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest gno.land/r/gnoswap/v1/common v0.0.0-latest gno.land/r/gnoswap/v1/consts v0.0.0-latest ) diff --git a/_deploy/r/gnoswap/gns/gns.gno b/_deploy/r/gnoswap/gns/gns.gno index cfe31927..20584c5e 100644 --- a/_deploy/r/gnoswap/gns/gns.gno +++ b/_deploy/r/gnoswap/gns/gns.gno @@ -9,6 +9,7 @@ import ( "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" "gno.land/r/gnoswap/v1/common" @@ -20,7 +21,7 @@ const MAXIMUM_SUPPLY = uint64(1_000_000_000_000_000) // 1B var ( banker *grc20.Teller admin *ownable.Ownable - token *grc20.Token + Token *grc20.Token ledger *grc20.PrivateLedger ) @@ -31,10 +32,13 @@ var ( func init() { admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - token, ledger = grc20.NewToken("Gnoswap", "GNS", 6) + Token, ledger = grc20.NewToken("Gnoswap", "GNS", 6) ledger.Mint(admin.Owner(), 100_000_000_000_000) // 100_000_000 GNS ≈ 0.1B + getter := func() *grc20.Token { return Token } + grc20reg.Register(getter, "") + amountToEmission = MAXIMUM_SUPPLY - uint64(100_000_000_000_000) lastMintedHeight = std.GetHeight() From 2fe48bf4f0f094943b1cea9e32a5a81019234834 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 18:15:38 +0900 Subject: [PATCH 03/30] feat: update grc20 spec for grc20reg --- __local/grc20_tokens/onbloc/bar/bar.gno | 4 +- __local/grc20_tokens/onbloc/baz/baz.gno | 33 +++++++------- __local/grc20_tokens/onbloc/foo/foo.gno | 33 +++++++------- __local/grc20_tokens/onbloc/obl/obl.gno | 33 +++++++------- __local/grc20_tokens/onbloc/qux/qux.gno | 33 +++++++------- __local/grc20_tokens/onbloc/usdc/usdc.gno | 33 +++++++------- _deploy/r/gnoswap/gns/gns.gno | 53 +++++++++++------------ 7 files changed, 108 insertions(+), 114 deletions(-) diff --git a/__local/grc20_tokens/onbloc/bar/bar.gno b/__local/grc20_tokens/onbloc/bar/bar.gno index 0be389fd..05f9086b 100644 --- a/__local/grc20_tokens/onbloc/bar/bar.gno +++ b/__local/grc20_tokens/onbloc/bar/bar.gno @@ -68,11 +68,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/__local/grc20_tokens/onbloc/baz/baz.gno b/__local/grc20_tokens/onbloc/baz/baz.gno index d40f18a7..c1dbdca1 100644 --- a/__local/grc20_tokens/onbloc/baz/baz.gno +++ b/__local/grc20_tokens/onbloc/baz/baz.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Baz", "BAZ", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Baz", "BAZ", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { @@ -68,11 +67,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/__local/grc20_tokens/onbloc/foo/foo.gno b/__local/grc20_tokens/onbloc/foo/foo.gno index 87dcbe32..e99ee1d9 100644 --- a/__local/grc20_tokens/onbloc/foo/foo.gno +++ b/__local/grc20_tokens/onbloc/foo/foo.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Baz", "BAZ", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Foo", "FOO", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { @@ -68,11 +67,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/__local/grc20_tokens/onbloc/obl/obl.gno b/__local/grc20_tokens/onbloc/obl/obl.gno index 0815952c..976cc088 100644 --- a/__local/grc20_tokens/onbloc/obl/obl.gno +++ b/__local/grc20_tokens/onbloc/obl/obl.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Obl", "OBL", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Obl", "OBL", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { @@ -68,11 +67,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/__local/grc20_tokens/onbloc/qux/qux.gno b/__local/grc20_tokens/onbloc/qux/qux.gno index 747ce978..29aaec1b 100644 --- a/__local/grc20_tokens/onbloc/qux/qux.gno +++ b/__local/grc20_tokens/onbloc/qux/qux.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Qux", "QUX", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Qux", "QUX", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { @@ -68,11 +67,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/__local/grc20_tokens/onbloc/usdc/usdc.gno b/__local/grc20_tokens/onbloc/usdc/usdc.gno index 9477bf0b..c0469bd1 100644 --- a/__local/grc20_tokens/onbloc/usdc/usdc.gno +++ b/__local/grc20_tokens/onbloc/usdc/usdc.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Usd Coin", "USDC", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Usd Coin", "USDC", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { @@ -68,11 +67,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" diff --git a/_deploy/r/gnoswap/gns/gns.gno b/_deploy/r/gnoswap/gns/gns.gno index 20584c5e..327ffb44 100644 --- a/_deploy/r/gnoswap/gns/gns.gno +++ b/_deploy/r/gnoswap/gns/gns.gno @@ -19,23 +19,18 @@ import ( const MAXIMUM_SUPPLY = uint64(1_000_000_000_000_000) // 1B var ( - banker *grc20.Teller - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + lastMintedHeight int64 + amountToEmission uint64 ) var ( - lastMintedHeight int64 - amountToEmission uint64 + Token, privateLedger = grc20.NewToken("Gnoswap", "GNS", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Gnoswap", "GNS", 6) - - ledger.Mint(admin.Owner(), 100_000_000_000_000) // 100_000_000 GNS ≈ 0.1B - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) // 100_000_000 GNS ≈ 0.1B getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") @@ -46,41 +41,39 @@ func init() { func GetAmountToEmission() uint64 { return amountToEmission } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} -func TotalMinted() uint64 { return token.TotalSupply() - uint64(100_000_000_000_000) } +func TotalMinted() uint64 { + return UserTeller.TotalSupply() - uint64(100_000_000_000_000) +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { - common.IsHalted() - toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { - common.IsHalted() - spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { - common.IsHalted() - fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Render(path string) string { @@ -89,11 +82,11 @@ func Render(path string) string { switch { case path == "": - return token.RenderHome() + return Token.RenderHome() case c == 2 && parts[0] == "balance": owner := pusers.AddressOrName(parts[1]) ownerAddr := users.Resolve(owner) - balance := token.BalanceOf(ownerAddr) + balance := UserTeller.BalanceOf(ownerAddr) return ufmt.Sprintf("%d\n", balance) default: return "404\n" @@ -150,7 +143,7 @@ func Mint(address pusers.AddressOrName) uint64 { } } - err := ledger.Mint(users.Resolve(address), amountToMint) + err := privateLedger.Mint(users.Resolve(address), amountToMint) if err != nil { panic(err.Error()) } @@ -160,6 +153,12 @@ func Mint(address pusers.AddressOrName) uint64 { return amountToMint } +func Burn(from pusers.AddressOrName, amount uint64) { + owner.AssertCallerIsOwner() + fromAddr := users.Resolve(from) + checkErr(privateLedger.Burn(fromAddr, amount)) +} + func checkAndHandleIfLastBlockOfHalvingYear(height int64, amount uint64) uint64 { year := GetHalvingYearByHeight(height) lastBlock := halvingYearBlock[year] From a5f0a56a6a4d35c65210e327c555aa3593dac905 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 18:25:37 +0900 Subject: [PATCH 04/30] hotfix: update bar token spec --- __local/grc20_tokens/onbloc/bar/bar.gno | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/__local/grc20_tokens/onbloc/bar/bar.gno b/__local/grc20_tokens/onbloc/bar/bar.gno index 05f9086b..d3d998e8 100644 --- a/__local/grc20_tokens/onbloc/bar/bar.gno +++ b/__local/grc20_tokens/onbloc/bar/bar.gno @@ -13,53 +13,52 @@ import ( ) var ( - admin *ownable.Ownable - Token *grc20.Token - ledger *grc20.PrivateLedger + Token, privateLedger = grc20.NewToken("Bar", "BAR", 6) + UserTeller = Token.CallerTeller() + owner = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN ) func init() { - admin = ownable.NewWithAddress("g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d") // ADMIN - Token, ledger = grc20.NewToken("Bar", "BAR", 6) - ledger.Mint(admin.Owner(), 100_000_000_000_000) - + privateLedger.Mint(owner.Owner(), 100_000_000_000_000) getter := func() *grc20.Token { return Token } grc20reg.Register(getter, "") } -func TotalSupply() uint64 { return token.TotalSupply() } +func TotalSupply() uint64 { + return UserTeller.TotalSupply() +} func BalanceOf(owner pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) - return token.BalanceOf(ownerAddr) + return UserTeller.BalanceOf(ownerAddr) } func Allowance(owner, spender pusers.AddressOrName) uint64 { ownerAddr := users.Resolve(owner) spenderAddr := users.Resolve(spender) - return token.Allowance(ownerAddr, spenderAddr) + return UserTeller.Allowance(ownerAddr, spenderAddr) } func Transfer(to pusers.AddressOrName, amount uint64) { toAddr := users.Resolve(to) - checkErr(token.CallerTeller().Transfer(toAddr, amount)) + checkErr(UserTeller.Transfer(toAddr, amount)) } func Approve(spender pusers.AddressOrName, amount uint64) { spenderAddr := users.Resolve(spender) - checkErr(token.CallerTeller().Approve(spenderAddr, amount)) + checkErr(UserTeller.Approve(spenderAddr, amount)) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { fromAddr := users.Resolve(from) toAddr := users.Resolve(to) - checkErr(token.CallerTeller().TransferFrom(fromAddr, toAddr, amount)) + checkErr(UserTeller.TransferFrom(fromAddr, toAddr, amount)) } func Burn(from pusers.AddressOrName, amount uint64) { - admin.AssertCallerIsOwner() + owner.AssertCallerIsOwner() fromAddr := users.Resolve(from) - checkErr(ledger.Burn(fromAddr, amount)) + checkErr(privateLedger.Burn(fromAddr, amount)) } func Render(path string) string { From 497b6580a64369bdeaedcbd693b417ced602fea4 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 18:59:57 +0900 Subject: [PATCH 05/30] feat: get token object from `grc20-reg` in `common` --- _deploy/r/gnoswap/common/grc20reg_helper.gno | 12 +++++++++ .../r/gnoswap/common/grc20reg_helper_test.gno | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 _deploy/r/gnoswap/common/grc20reg_helper.gno create mode 100644 _deploy/r/gnoswap/common/grc20reg_helper_test.gno diff --git a/_deploy/r/gnoswap/common/grc20reg_helper.gno b/_deploy/r/gnoswap/common/grc20reg_helper.gno new file mode 100644 index 00000000..f61c551e --- /dev/null +++ b/_deploy/r/gnoswap/common/grc20reg_helper.gno @@ -0,0 +1,12 @@ +package common + +import ( + "gno.land/p/demo/grc/grc20" + "gno.land/r/demo/grc20reg" +) + +func GetToken(path string) grc20.Teller { + tokenGetter := grc20reg.MustGet(path) // if token is not registered, it will panic + token := tokenGetter() + return token.CallerTeller() +} diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno new file mode 100644 index 00000000..46687a59 --- /dev/null +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -0,0 +1,25 @@ +package common + +import ( + "testing" + + _ "gno.land/r/demo/wugnot" +) + +func TestGetToken(t *testing.T) { + t.Run("registered(by default)", func(t *testing.T) { + token := GetToken("gno.land/r/demo/wugnot") + if token == nil { + t.Error("Expected non-nil teller for WUGNOT") + } + }) + + t.Run("not registered", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected panic for non-registered token") + } + }() + GetToken("not_registered") + }) +} From 735ac70a7f0460598e8906795ddf6e655d008b4c Mon Sep 17 00:00:00 2001 From: n3wbie Date: Thu, 5 Dec 2024 10:58:00 +0900 Subject: [PATCH 06/30] fix: typo --- __local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar b/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar index 03b160b9..ff43ac44 100644 --- a/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar +++ b/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar @@ -3,7 +3,7 @@ loadpkg gno.land/p/demo/users loadpkg gno.land/r/demo/foo20 loadpkg gno.land/r/demo/grc20reg -loadpkg gno.land/r/demo/echo $WORK/echo +loadpkg gno.land/r/demo/reg $WORK/reg ## start a new node gnoland start From 52caa14e0783803ef725624dfc635acf46491ea1 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 10:32:16 +0900 Subject: [PATCH 07/30] chore: remove grc20reg - it's been merged into master of gnolang/gno --- .../grc20reg/approve_and_transferfrom.txtar | 53 ------------- __local/grc20_tokens/grc20reg/gno.mod | 9 --- __local/grc20_tokens/grc20reg/grc20reg.gno | 76 ------------------- .../grc20_tokens/grc20reg/grc20reg_test.gno | 59 -------------- 4 files changed, 197 deletions(-) delete mode 100644 __local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar delete mode 100644 __local/grc20_tokens/grc20reg/gno.mod delete mode 100644 __local/grc20_tokens/grc20reg/grc20reg.gno delete mode 100644 __local/grc20_tokens/grc20reg/grc20reg_test.gno diff --git a/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar b/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar deleted file mode 100644 index ff43ac44..00000000 --- a/__local/grc20_tokens/grc20reg/approve_and_transferfrom.txtar +++ /dev/null @@ -1,53 +0,0 @@ -loadpkg gno.land/p/demo/users - -loadpkg gno.land/r/demo/foo20 -loadpkg gno.land/r/demo/grc20reg - -loadpkg gno.land/r/demo/reg $WORK/reg - -## start a new node -gnoland start - -## faucet -# gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Faucet -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 - -## print reg addr -gnokey maketx call -pkgpath gno.land/r/demo/reg -func RelamAddr -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 -stdout 'g19tlskvga928es8ug2empargp0teul03apzjud9' - -## approve -gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Approve -args 'g19tlskvga928es8ug2empargp0teul03apzjud9' -args '100' -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 - -## transfer from -gnokey maketx call -pkgpath gno.land/r/demo/reg -func TransferFromWithReg -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 -stdout '' - --- reg/reg.gno -- -package reg - -import ( - "std" - - "gno.land/r/demo/grc20reg" -) - -func RelamAddr() string { - addr := std.CurrentRealm().Addr().String() - return addr -} - -func TransferFromWithReg() { - caller := std.PrevRealm().Addr() - curr := std.CurrentRealm().Addr() - - - // using import - // foo20.TransferFrom(uCaller, uCurr, uint64(100)) - - // using grc20reg - fooTokenGetter := grc20reg.Get("gno.land/r/demo/foo20") - fooToken := fooTokenGetter() - userTeller := fooToken.CallerTeller() - - userTeller.TransferFrom(caller, curr, uint64(100)) -} \ No newline at end of file diff --git a/__local/grc20_tokens/grc20reg/gno.mod b/__local/grc20_tokens/grc20reg/gno.mod deleted file mode 100644 index 450e21be..00000000 --- a/__local/grc20_tokens/grc20reg/gno.mod +++ /dev/null @@ -1,9 +0,0 @@ -module gno.land/r/gnoswap/v1/grc20reg - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/fqname v0.0.0-latest - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) \ No newline at end of file diff --git a/__local/grc20_tokens/grc20reg/grc20reg.gno b/__local/grc20_tokens/grc20reg/grc20reg.gno deleted file mode 100644 index ff46ec94..00000000 --- a/__local/grc20_tokens/grc20reg/grc20reg.gno +++ /dev/null @@ -1,76 +0,0 @@ -package grc20reg - -import ( - "std" - - "gno.land/p/demo/avl" - "gno.land/p/demo/fqname" - "gno.land/p/demo/grc/grc20" - "gno.land/p/demo/ufmt" -) - -var registry = avl.NewTree() // rlmPath[.slug] -> TokenGetter (slug is optional) - -func Register(tokenGetter grc20.TokenGetter, slug string) { - rlmPath := std.PrevRealm().PkgPath() - key := fqname.Construct(rlmPath, slug) - registry.Set(key, tokenGetter) - std.Emit( - registerEvent, - "pkgpath", rlmPath, - "slug", slug, - ) -} - -func Get(key string) grc20.TokenGetter { - tokenGetter, ok := registry.Get(key) - if !ok { - return nil - } - return tokenGetter.(grc20.TokenGetter) -} - -func MustGet(key string) grc20.TokenGetter { - tokenGetter := Get(key) - if tokenGetter == nil { - panic("unknown token: " + key) - } - return tokenGetter -} - -func Render(path string) string { - switch { - case path == "": // home - // TODO: add pagination - s := "" - count := 0 - registry.Iterate("", "", func(key string, tokenI interface{}) bool { - count++ - tokenGetter := tokenI.(grc20.TokenGetter) - token := tokenGetter() - rlmPath, slug := fqname.Parse(key) - rlmLink := fqname.RenderLink(rlmPath, slug) - infoLink := "/r/demo/grc20reg:" + key - s += ufmt.Sprintf("- **%s** - %s - [info](%s)\n", token.GetName(), rlmLink, infoLink) - return false - }) - if count == 0 { - return "No registered token." - } - return s - default: // specific token - key := path - tokenGetter := MustGet(key) - token := tokenGetter() - rlmPath, slug := fqname.Parse(key) - rlmLink := fqname.RenderLink(rlmPath, slug) - s := ufmt.Sprintf("# %s\n", token.GetName()) - s += ufmt.Sprintf("- symbol: **%s**\n", token.GetSymbol()) - s += ufmt.Sprintf("- realm: %s\n", rlmLink) - s += ufmt.Sprintf("- decimals: %d\n", token.GetDecimals()) - s += ufmt.Sprintf("- total supply: %d\n", token.TotalSupply()) - return s - } -} - -const registerEvent = "register" diff --git a/__local/grc20_tokens/grc20reg/grc20reg_test.gno b/__local/grc20_tokens/grc20reg/grc20reg_test.gno deleted file mode 100644 index c93365ff..00000000 --- a/__local/grc20_tokens/grc20reg/grc20reg_test.gno +++ /dev/null @@ -1,59 +0,0 @@ -package grc20reg - -import ( - "std" - "strings" - "testing" - - "gno.land/p/demo/grc/grc20" - "gno.land/p/demo/urequire" -) - -func TestRegistry(t *testing.T) { - std.TestSetRealm(std.NewCodeRealm("gno.land/r/demo/foo")) - realmAddr := std.CurrentRealm().PkgPath() - token, ledger := grc20.NewToken("TestToken", "TST", 4) - ledger.Mint(std.CurrentRealm().Addr(), 1234567) - tokenGetter := func() *grc20.Token { return token } - // register - Register(tokenGetter, "") - regTokenGetter := Get(realmAddr) - regToken := regTokenGetter() - urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil - urequire.Equal(t, regToken.GetSymbol(), "TST") - - expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo) -` - got := Render("") - urequire.True(t, strings.Contains(got, expected)) - // 404 - invalidToken := Get("0xdeadbeef") - urequire.True(t, invalidToken == nil) - - // register with a slug - Register(tokenGetter, "mySlug") - regTokenGetter = Get(realmAddr + ".mySlug") - regToken = regTokenGetter() - urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil - urequire.Equal(t, regToken.GetSymbol(), "TST") - - // override - Register(tokenGetter, "") - regTokenGetter = Get(realmAddr + "") - regToken = regTokenGetter() - urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil - urequire.Equal(t, regToken.GetSymbol(), "TST") - - got = Render("") - urequire.True(t, strings.Contains(got, `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo)`)) - urequire.True(t, strings.Contains(got, `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).mySlug - [info](/r/demo/grc20reg:gno.land/r/demo/foo.mySlug)`)) - - expected = `# TestToken -- symbol: **TST** -- realm: [gno.land/r/demo/foo](/r/demo/foo).mySlug -- decimals: 4 -- total supply: 1234567 -` - got = Render("gno.land/r/demo/foo.mySlug") - urequire.Equal(t, expected, got) -} From 309a4b226cc271221a32002511708f0bd602a9dc Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 11:19:07 +0900 Subject: [PATCH 08/30] feat: get `token` and `teller` object from grc20reg --- _deploy/r/gnoswap/common/grc20reg_helper.gno | 26 ++++- .../r/gnoswap/common/grc20reg_helper_test.gno | 104 +++++++++++++++++- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/_deploy/r/gnoswap/common/grc20reg_helper.gno b/_deploy/r/gnoswap/common/grc20reg_helper.gno index f61c551e..e8c17e3a 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper.gno @@ -2,10 +2,34 @@ package common import ( "gno.land/p/demo/grc/grc20" + "gno.land/r/demo/grc20reg" ) -func GetToken(path string) grc20.Teller { +// GetToken returns a grc20.Token instance +// if token is not registered, it will panic +// token instance supports following methods: +// - GetName +// - GetSymbol +// - GetDecimals +// - TotalSupply +// - KnownAccounts +// - BalanceOf +// - Allowance +// - RenderHome +func GetToken(path string) *grc20.Token { + tokenGetter := grc20reg.MustGet(path) // if token is not registered, it will panic + + return tokenGetter() +} + +// GetTokenTeller returns a grc20.Teller instance +// if token is not registered, it will panic +// teller instance supports following methods: +// - Transfer +// - Approve +// - TransferFrom +func GetTokenTeller(path string) grc20.Teller { tokenGetter := grc20reg.MustGet(path) // if token is not registered, it will panic token := tokenGetter() return token.CallerTeller() diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno index 46687a59..e5aba65b 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -1,14 +1,19 @@ package common import ( + "std" "testing" - _ "gno.land/r/demo/wugnot" + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + "gno.land/p/demo/ufmt" + + _ "gno.land/r/demo/foo20" ) func TestGetToken(t *testing.T) { t.Run("registered(by default)", func(t *testing.T) { - token := GetToken("gno.land/r/demo/wugnot") + token := GetToken("gno.land/r/demo/foo20") if token == nil { t.Error("Expected non-nil teller for WUGNOT") } @@ -23,3 +28,98 @@ func TestGetToken(t *testing.T) { GetToken("not_registered") }) } + +func TestTokenMethod(t *testing.T) { + token := GetToken("gno.land/r/demo/foo20") + + t.Run("GetName()", func(t *testing.T) { + uassert.Equal(t, "Foo", token.GetName()) + }) + + t.Run("GetSymbol()", func(t *testing.T) { + uassert.Equal(t, "FOO", token.GetSymbol()) + }) + + t.Run("GetDecimals()", func(t *testing.T) { + uassert.Equal(t, uint(4), token.GetDecimals()) + }) + + t.Run("TotalSupply()", func(t *testing.T) { + uassert.Equal(t, uint64(10000000000), token.TotalSupply()) + }) + + t.Run("KnownAccounts()", func(t *testing.T) { + uassert.Equal(t, int(1), token.KnownAccounts()) + }) + + t.Run("BalanceOf()", func(t *testing.T) { + uassert.Equal(t, uint64(10000000000), token.BalanceOf(std.Address("g1manfred47kzduec920z88wfr64ylksmdcedlf5"))) + }) + + t.Run("Allowance()", func(t *testing.T) { + uassert.Equal(t, uint64(0), token.Allowance(std.Address("g1manfred47kzduec920z88wfr64ylksmdcedlf5"), std.Address("g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6"))) + }) + + t.Run("RenderHome()", func(t *testing.T) { + expected := "" + expected += ufmt.Sprintf("# %s ($%s)\n\n", "Foo", "FOO") + expected += ufmt.Sprintf("* **Decimals**: %d\n", 4) + expected += ufmt.Sprintf("* **Total supply**: %d\n", 10000000000) + expected += ufmt.Sprintf("* **Known accounts**: %d\n", 1) + uassert.Equal(t, expected, token.RenderHome()) + }) +} + +func TestGetTokenTeller(t *testing.T) { + t.Run("registered(by default)", func(t *testing.T) { + teller := GetTokenTeller("gno.land/r/demo/foo20") + if teller == nil { + t.Error("Expected non-nil teller for WUGNOT") + } + }) + + t.Run("not registered", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected panic for non-registered token") + } + }() + GetTokenTeller("not_registered") + }) +} + +func TestTellerMethod(t *testing.T) { + teller := GetTokenTeller("gno.land/r/demo/foo20") + token := GetToken("gno.land/r/demo/foo20") + defaultHolder := std.Address("g1manfred47kzduec920z88wfr64ylksmdcedlf5") + addr01 := testutils.TestAddress("addr01") + + t.Run("Transfer()", func(t *testing.T) { + std.TestSetRealm(std.NewUserRealm(defaultHolder)) + + uassert.Equal(t, uint64(10000000000), token.BalanceOf(defaultHolder)) + + uassert.NoError(t, teller.Transfer(addr01, uint64(10000000000))) // transfer all balance to addr01 + + uassert.Equal(t, uint64(0), token.BalanceOf(defaultHolder)) + uassert.Equal(t, uint64(10000000000), token.BalanceOf(addr01)) + + uassert.Error(t, teller.Transfer(addr01, uint64(10000000000))) // not enough balance + }) + + t.Run("Approve()", func(t *testing.T) { + std.TestSetRealm(std.NewUserRealm(addr01)) + uassert.NoError(t, teller.Approve(defaultHolder, uint64(500))) + uassert.Equal(t, uint64(500), token.Allowance(addr01, defaultHolder)) + }) + + t.Run("TransferFrom()", func(t *testing.T) { + std.TestSetRealm(std.NewUserRealm(defaultHolder)) + uassert.NoError(t, teller.TransferFrom(addr01, defaultHolder, uint64(500))) + uassert.Equal(t, uint64(9999999500), token.BalanceOf(addr01)) + uassert.Equal(t, uint64(500), token.BalanceOf(defaultHolder)) + uassert.Equal(t, uint64(0), token.Allowance(addr01, defaultHolder)) + + uassert.Error(t, teller.TransferFrom(addr01, defaultHolder, uint64(500))) // not enough allowance + }) +} From 2244fb43fd94a5c0dc56ce5376b0d137e66118a0 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 12:00:39 +0900 Subject: [PATCH 09/30] test: txtar for approve & transferfrom using grc20reg --- .../grc20reg/approve_transferfrom.txtar | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 __local/grc20_tokens/grc20reg/approve_transferfrom.txtar diff --git a/__local/grc20_tokens/grc20reg/approve_transferfrom.txtar b/__local/grc20_tokens/grc20reg/approve_transferfrom.txtar new file mode 100644 index 00000000..ff43ac44 --- /dev/null +++ b/__local/grc20_tokens/grc20reg/approve_transferfrom.txtar @@ -0,0 +1,53 @@ +loadpkg gno.land/p/demo/users + +loadpkg gno.land/r/demo/foo20 +loadpkg gno.land/r/demo/grc20reg + +loadpkg gno.land/r/demo/reg $WORK/reg + +## start a new node +gnoland start + +## faucet +# gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Faucet -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 + +## print reg addr +gnokey maketx call -pkgpath gno.land/r/demo/reg -func RelamAddr -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 +stdout 'g19tlskvga928es8ug2empargp0teul03apzjud9' + +## approve +gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Approve -args 'g19tlskvga928es8ug2empargp0teul03apzjud9' -args '100' -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 + +## transfer from +gnokey maketx call -pkgpath gno.land/r/demo/reg -func TransferFromWithReg -gas-fee 1ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 +stdout '' + +-- reg/reg.gno -- +package reg + +import ( + "std" + + "gno.land/r/demo/grc20reg" +) + +func RelamAddr() string { + addr := std.CurrentRealm().Addr().String() + return addr +} + +func TransferFromWithReg() { + caller := std.PrevRealm().Addr() + curr := std.CurrentRealm().Addr() + + + // using import + // foo20.TransferFrom(uCaller, uCurr, uint64(100)) + + // using grc20reg + fooTokenGetter := grc20reg.Get("gno.land/r/demo/foo20") + fooToken := fooTokenGetter() + userTeller := fooToken.CallerTeller() + + userTeller.TransferFrom(caller, curr, uint64(100)) +} \ No newline at end of file From bba3ee4d0bfb485bca9dc4566b0255ca81093fc2 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 18:15:48 +0900 Subject: [PATCH 10/30] feat: use teller to transfer token --- pool/pool.gno | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pool/pool.gno b/pool/pool.gno index 0ce792a6..76286a22 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -142,6 +142,8 @@ func Collect( var amount0, amount1 *u256.Uint + var amount0, amount1 *u256.Uint + // Smallest of three: amount0Requested, position.tokensOwed0, pool.balances.token0 amount0Req := u256.MustFromDecimal(amount0Requested) amount0, position.tokensOwed0, pool.balances.token0 = collectToken(amount0Req, position.tokensOwed0, pool.balances.token0) @@ -822,10 +824,10 @@ func collectProtocol( uAmount0 := amount0.Uint64() uAmount1 := amount1.Uint64() - token0 := common.GetToken(pool.token0Path) + token0 := common.GetTokenTeller(pool.token0Path) checkTransferError(token0.Transfer(recipient, uAmount0)) - token1 := common.GetToken(pool.token1Path) + token1 := common.GetTokenTeller(pool.token1Path) checkTransferError(token1.Transfer(recipient, uAmount1)) return amount0.ToString(), amount1.ToString() @@ -954,7 +956,7 @@ func (pool *Pool) transferFromAndVerify( panic(err) } - token := common.GetToken(tokenPath) + token := common.GetTokenTeller(tokenPath) checkTransferError(token.TransferFrom(from, to, amountUint64)) // update pool balances From 747f9ae0f61d23ce6717909988b9fb912691ab2b Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 19:01:48 +0900 Subject: [PATCH 11/30] feat: IsRegistered() to check if token is registered or not --- _deploy/r/gnoswap/common/grc20reg_helper.gno | 12 +++++++++- .../r/gnoswap/common/grc20reg_helper_test.gno | 23 +++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/_deploy/r/gnoswap/common/grc20reg_helper.gno b/_deploy/r/gnoswap/common/grc20reg_helper.gno index e8c17e3a..239c42ca 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper.gno @@ -2,7 +2,7 @@ package common import ( "gno.land/p/demo/grc/grc20" - + "gno.land/p/demo/ufmt" "gno.land/r/demo/grc20reg" ) @@ -34,3 +34,13 @@ func GetTokenTeller(path string) grc20.Teller { token := tokenGetter() return token.CallerTeller() } + +// IsRegistered returns nil if token is registered to grc20reg +// otherwise, it returns an error +func IsRegistered(path string) error { + getter := grc20reg.Get(path) + if getter == nil { + return ufmt.Errorf("token(%s) is not registered to grc20reg", path) + } + return nil +} diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno index e5aba65b..4287a62d 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -11,11 +11,15 @@ import ( _ "gno.land/r/demo/foo20" ) +var ( + tokenPath = "gno.land/r/demo/foo20" +) + func TestGetToken(t *testing.T) { t.Run("registered(by default)", func(t *testing.T) { - token := GetToken("gno.land/r/demo/foo20") + token := GetToken(tokenPath) if token == nil { - t.Error("Expected non-nil teller for WUGNOT") + t.Error("Expected non-nil teller for foo20") } }) @@ -30,7 +34,7 @@ func TestGetToken(t *testing.T) { } func TestTokenMethod(t *testing.T) { - token := GetToken("gno.land/r/demo/foo20") + token := GetToken(tokenPath) t.Run("GetName()", func(t *testing.T) { uassert.Equal(t, "Foo", token.GetName()) @@ -72,9 +76,9 @@ func TestTokenMethod(t *testing.T) { func TestGetTokenTeller(t *testing.T) { t.Run("registered(by default)", func(t *testing.T) { - teller := GetTokenTeller("gno.land/r/demo/foo20") + teller := GetTokenTeller(tokenPath) if teller == nil { - t.Error("Expected non-nil teller for WUGNOT") + t.Error("Expected non-nil teller for foo20") } }) @@ -89,8 +93,8 @@ func TestGetTokenTeller(t *testing.T) { } func TestTellerMethod(t *testing.T) { - teller := GetTokenTeller("gno.land/r/demo/foo20") - token := GetToken("gno.land/r/demo/foo20") + teller := GetTokenTeller(tokenPath) + token := GetToken(tokenPath) defaultHolder := std.Address("g1manfred47kzduec920z88wfr64ylksmdcedlf5") addr01 := testutils.TestAddress("addr01") @@ -123,3 +127,8 @@ func TestTellerMethod(t *testing.T) { uassert.Error(t, teller.TransferFrom(addr01, defaultHolder, uint64(500))) // not enough allowance }) } + +func TestIsRegistered(t *testing.T) { + uassert.NoError(t, IsRegistered(tokenPath)) + uassert.Error(t, IsRegistered("not_registered")) +} From 08f69a6b9928ad675991b9f5e9c793bec5387188 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 6 Dec 2024 19:22:33 +0900 Subject: [PATCH 12/30] refactor: remove old token_register --- pool/token_register.gno | 153 ---------------------------------------- 1 file changed, 153 deletions(-) delete mode 100644 pool/token_register.gno diff --git a/pool/token_register.gno b/pool/token_register.gno deleted file mode 100644 index 419b2ee4..00000000 --- a/pool/token_register.gno +++ /dev/null @@ -1,153 +0,0 @@ -package pool - -import ( - "std" - "strings" - - "gno.land/p/demo/ufmt" - pusers "gno.land/p/demo/users" - - "gno.land/r/gnoswap/v1/common" - "gno.land/r/gnoswap/v1/consts" -) - -// GRC20Interface is the interface for GRC20 tokens -// It is used to interact with the GRC20 tokens without importing but by registering each tokens function -type GRC20Interface interface { - Transfer() func(to pusers.AddressOrName, amount uint64) - TransferFrom() func(from, to pusers.AddressOrName, amount uint64) - BalanceOf() func(owner pusers.AddressOrName) uint64 - Approve() func(spender pusers.AddressOrName, amount uint64) -} - -var ( - registered = make(map[string]GRC20Interface) -) - -// GetRegisteredTokens returns a list of all registered tokens -func GetRegisteredTokens() []string { - tokens := make([]string, 0, len(registered)) - for k := range registered { - tokens = append(tokens, k) - } - return tokens -} - -// RegisterGRC20Interface registers a GRC20 token interface -func RegisterGRC20Interface(pkgPath string, igrc20 GRC20Interface) { - prevAddr := std.PrevRealm().Addr() - prevPath := std.PrevRealm().PkgPath() - if !(prevAddr == consts.TOKEN_REGISTER || prevPath == consts.INIT_REGISTER_PATH || strings.HasPrefix(prevPath, "gno.land/r/g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5")) { - panic(addDetailToError( - errNoPermission, - ufmt.Sprintf("token_register.gno__RegisterGRC20Interface() || only register(%s) can register token, called from %s", consts.TOKEN_REGISTER, prevAddr), - )) - } - - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if found { - panic(addDetailToError( - errAlreadyRegistered, - ufmt.Sprintf("token_register.gno__RegisterGRC20Interface() || token(%s) already registered", pkgPath), - )) - } - - registered[pkgPath] = igrc20 -} - -// UnregisterGRC20Interface unregisters a GRC20 token interface -func UnregisterGRC20Interface(pkgPath string) { - if err := common.SatisfyCond(isUserCall()); err != nil { - panic(addDetailToError( - errNoPermission, - ufmt.Sprintf("token_register.gno__UnregisterGRC20Interface() || unauthorized address(%s) to unregister", std.PrevRealm().Addr()), - )) - } - - caller := std.PrevRealm().Addr() - if err := common.TokenRegisterOnly(caller); err != nil { - panic(addDetailToError( - errNoPermission, - ufmt.Sprintf("token_register.gno__UnregisterGRC20Interface() || unauthorized address(%s) to unregister", caller), - )) - } - - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if found { - delete(registered, pkgPath) - } -} - -func transferByRegisterCall(pkgPath string, to std.Address, amount uint64) bool { - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if !found { - panic(addDetailToError( - errNotRegistered, - ufmt.Sprintf("token_register.gno__transferByRegisterCall() || token(%s) not registered", pkgPath), - )) - } - registered[pkgPath].Transfer()(pusers.AddressOrName(to), amount) - - return true -} - -func transferFromByRegisterCall(pkgPath string, from, to std.Address, amount uint64) bool { - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if !found { - panic(addDetailToError( - errNotRegistered, - ufmt.Sprintf("token_register.gno__transferFromByRegisterCall() || token(%s) not registered", pkgPath), - )) - } - - registered[pkgPath].TransferFrom()(pusers.AddressOrName(from), pusers.AddressOrName(to), amount) - - return true -} - -func balanceOfByRegisterCall(pkgPath string, owner std.Address) uint64 { - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if !found { - panic(addDetailToError( - errNotRegistered, - ufmt.Sprintf("token_register.gno__balanceOfByRegisterCall() || token(%s) not registered", pkgPath), - )) - } - - balance := registered[pkgPath].BalanceOf()(pusers.AddressOrName(owner)) - return balance -} - -func approveByRegisterCall(pkgPath string, spender std.Address, amount uint64) bool { - pkgPath = handleNative(pkgPath) - - _, found := registered[pkgPath] - if !found { - panic(addDetailToError( - errNotRegistered, - ufmt.Sprintf("token_register.gno__approveByRegisterCall() || token(%s) not registered", pkgPath), - )) - } - - registered[pkgPath].Approve()(pusers.AddressOrName(spender), amount) - - return true -} - -func handleNative(pkgPath string) string { - if pkgPath == consts.GNOT { - return consts.WRAPPED_WUGNOT - } - - return pkgPath -} From 32b18f3784ea433d523c6af5338cd6cef8b72f21 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Sun, 8 Dec 2024 23:35:29 +0900 Subject: [PATCH 13/30] chore: rename teller --- pool/pool.gno | 8 ++++---- pool/protocol_fee_withdrawal.gno | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pool/pool.gno b/pool/pool.gno index 76286a22..f6f8fa46 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -824,11 +824,11 @@ func collectProtocol( uAmount0 := amount0.Uint64() uAmount1 := amount1.Uint64() - token0 := common.GetTokenTeller(pool.token0Path) - checkTransferError(token0.Transfer(recipient, uAmount0)) + token0Teller := common.GetTokenTeller(pool.token0Path) + checkTransferError(token0Teller.Transfer(recipient, uAmount0)) - token1 := common.GetTokenTeller(pool.token1Path) - checkTransferError(token1.Transfer(recipient, uAmount1)) + token1Teller := common.GetTokenTeller(pool.token1Path) + checkTransferError(token1Teller.Transfer(recipient, uAmount1)) return amount0.ToString(), amount1.ToString() } diff --git a/pool/protocol_fee_withdrawal.gno b/pool/protocol_fee_withdrawal.gno index 4e79388f..bf55e2c2 100644 --- a/pool/protocol_fee_withdrawal.gno +++ b/pool/protocol_fee_withdrawal.gno @@ -64,8 +64,11 @@ func HandleWithdrawalFee( feeAmount0, afterAmount0 := calculateAmountWithFee(u256.MustFromDecimal(_amount0), u256.NewUint(fee)) feeAmount1, afterAmount1 := calculateAmountWithFee(u256.MustFromDecimal(_amount1), u256.NewUint(fee)) - transferFromByRegisterCall(token0Path, positionCaller, consts.PROTOCOL_FEE_ADDR, feeAmount0.Uint64()) - transferFromByRegisterCall(token1Path, positionCaller, consts.PROTOCOL_FEE_ADDR, feeAmount1.Uint64()) + token0Teller := common.GetTokenTeller(token0Path) + checkTransferError(token0Teller.TransferFrom(positionCaller, consts.PROTOCOL_FEE_ADDR, feeAmount0.Uint64())) + + token1Teller := common.GetTokenTeller(token1Path) + checkTransferError(token1Teller.TransferFrom(positionCaller, consts.PROTOCOL_FEE_ADDR, feeAmount1.Uint64())) prevAddr, prevPkgPath := getPrev() std.Emit( From be570a24257f7445c057a4bdc7010b107b3feedb Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 9 Dec 2024 00:00:39 +0900 Subject: [PATCH 14/30] feat: guard logic to see if token is registered --- _deploy/r/gnoswap/common/errors.gno | 7 +++-- _deploy/r/gnoswap/common/grc20reg_helper.gno | 9 ++++++ pool/pool.gno | 30 ++++++++++++++++---- pool/pool_manager.gno | 9 ++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/_deploy/r/gnoswap/common/errors.gno b/_deploy/r/gnoswap/common/errors.gno index 8cf952f2..43bd3133 100644 --- a/_deploy/r/gnoswap/common/errors.gno +++ b/_deploy/r/gnoswap/common/errors.gno @@ -7,9 +7,10 @@ import ( ) var ( - errNoPermission = errors.New("[GNOSWAP-COMMON-001] caller has no permission") - errHalted = errors.New("[GNOSWAP-COMMON-002] halted") - errOutOfRange = errors.New("[GNOSWAP-COMMON-003] value out of range") + errNoPermission = errors.New("[GNOSWAP-COMMON-001] caller has no permission") + errHalted = errors.New("[GNOSWAP-COMMON-002] halted") + errOutOfRange = errors.New("[GNOSWAP-COMMON-003] value out of range") + errNotRegistered = errors.New("[GNOSWAP-COMMON-004] token is not registered") ) func addDetailToError(err error, detail string) string { diff --git a/_deploy/r/gnoswap/common/grc20reg_helper.gno b/_deploy/r/gnoswap/common/grc20reg_helper.gno index 239c42ca..785b3f65 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper.gno @@ -44,3 +44,12 @@ func IsRegistered(path string) error { } return nil } + +func MustRegisteredToken(path string) { + if err := IsRegistered(path); err != nil { + panic(addDetailToError( + errNotRegistered, + ufmt.Sprintf("token(%s) is not registered", path), + )) + } +} diff --git a/pool/pool.gno b/pool/pool.gno index f6f8fa46..3f6c5911 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -28,6 +28,9 @@ func Mint( positionCaller std.Address, ) (string, string) { common.IsHalted() + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.PositionOnly(caller); err != nil { @@ -74,6 +77,9 @@ func Burn( liquidityAmount string, // uint128 ) (string, string) { // uint256 x2 common.IsHalted() + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + caller := std.PrevRealm().Addr() if common.GetLimitCaller() { if err := common.PositionOnly(caller); err != nil { @@ -119,6 +125,9 @@ func Collect( amount1Requested string, ) (string, string) { common.IsHalted() + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.PositionOnly(caller); err != nil { @@ -218,6 +227,9 @@ func Swap( payer std.Address, // router ) (string, string) { common.IsHalted() + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.RouterOnly(caller); err != nil { @@ -727,9 +739,12 @@ func CollectProtocolByAdmin( token1Path string, fee uint32, recipient std.Address, - amount0Requested string, - amount1Requested string, -) (string, string) { + _amount0Requested string, // uint128 + _amount1Requested string, // uint128 +) (string, string) { // uint128 x2 + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + caller := std.PrevRealm().Addr() if err := common.AdminOnly(caller); err != nil { panic(err) @@ -769,9 +784,12 @@ func CollectProtocol( token1Path string, fee uint32, recipient std.Address, - amount0Requested string, - amount1Requested string, -) (string, string) { + _amount0Requested string, // uint128 + _amount1Requested string, // uint128 +) (string, string) { // uint128 x2 + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + caller := std.PrevRealm().Addr() if err := common.GovernanceOnly(caller); err != nil { panic(err) diff --git a/pool/pool_manager.gno b/pool/pool_manager.gno index e6652805..88d48e68 100644 --- a/pool/pool_manager.gno +++ b/pool/pool_manager.gno @@ -150,6 +150,9 @@ func CreatePool( // wrap first token0Path, token1Path = poolInfo.wrap() + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + // reinitialize poolInfo with wrapped tokens poolInfo = newPoolParams(token0Path, token1Path, fee, _sqrtPriceX96) @@ -224,6 +227,9 @@ func DoesPoolPathExist(poolPath string) bool { // It constructs the poolPath from the given parameters and returns the corresponding pool. // Returns pool struct func GetPool(token0Path, token1Path string, fee uint32) *Pool { + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + poolPath := GetPoolPath(token0Path, token1Path, fee) pool, exist := pools[poolPath] if !exist { @@ -252,6 +258,9 @@ func GetPoolFromPoolPath(poolPath string) *Pool { // GetPoolPath generates a poolPath from the given token paths and fee. // The poolPath is constructed by joining the token paths and fee with colons. func GetPoolPath(token0Path, token1Path string, fee uint32) string { + common.MustRegisteredToken(token0Path) + common.MustRegisteredToken(token1Path) + // TODO: this check is not unnecessary, if we are sure that // all the token paths in the pool are sorted in alphabetical order. if strings.Compare(token1Path, token0Path) < 0 { From 14b7e71277741b9b94d7314a2e104c4811c0b793 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 9 Dec 2024 10:53:28 +0900 Subject: [PATCH 15/30] feat: MustRegistered in common - if token is not registered, it will panic. --- _deploy/r/gnoswap/common/grc20reg_helper.gno | 4 +++- .../r/gnoswap/common/grc20reg_helper_test.gno | 24 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/_deploy/r/gnoswap/common/grc20reg_helper.gno b/_deploy/r/gnoswap/common/grc20reg_helper.gno index 785b3f65..50f945e0 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper.gno @@ -45,7 +45,9 @@ func IsRegistered(path string) error { return nil } -func MustRegisteredToken(path string) { +// MustRegistered is a helper function to check if token is registered to grc20reg +// if token is not registered, it will panic +func MustRegistered(path string) { if err := IsRegistered(path); err != nil { panic(addDetailToError( errNotRegistered, diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno index 4287a62d..023461f1 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -129,6 +129,26 @@ func TestTellerMethod(t *testing.T) { } func TestIsRegistered(t *testing.T) { - uassert.NoError(t, IsRegistered(tokenPath)) - uassert.Error(t, IsRegistered("not_registered")) + t.Run("registered(by default)", func(t *testing.T) { + uassert.NoError(t, IsRegistered(tokenPath)) + }) + + t.Run("not registered", func(t *testing.T) { + uassert.Error(t, IsRegistered("not_registered")) + }) +} + +func TestMustRegistered(t *testing.T) { + t.Run("registered(by default)", func(t *testing.T) { + MustRegistered(tokenPath) + }) + + t.Run("not registered", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected panic for non-registered token") + } + }() + MustRegistered("not_registered") + }) } From 0cfd449a2ab8fe76c62e95abb7aefc668dbe2c78 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 9 Dec 2024 10:54:49 +0900 Subject: [PATCH 16/30] chore: rename --- pool/pool.gno | 24 ++++++++++++------------ pool/pool_manager.gno | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pool/pool.gno b/pool/pool.gno index 3f6c5911..3980adcf 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -28,8 +28,8 @@ func Mint( positionCaller std.Address, ) (string, string) { common.IsHalted() - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) if common.GetLimitCaller() { caller := std.PrevRealm().Addr() @@ -77,8 +77,8 @@ func Burn( liquidityAmount string, // uint128 ) (string, string) { // uint256 x2 common.IsHalted() - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) caller := std.PrevRealm().Addr() if common.GetLimitCaller() { @@ -125,8 +125,8 @@ func Collect( amount1Requested string, ) (string, string) { common.IsHalted() - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) if common.GetLimitCaller() { caller := std.PrevRealm().Addr() @@ -227,8 +227,8 @@ func Swap( payer std.Address, // router ) (string, string) { common.IsHalted() - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) if common.GetLimitCaller() { caller := std.PrevRealm().Addr() @@ -742,8 +742,8 @@ func CollectProtocolByAdmin( _amount0Requested string, // uint128 _amount1Requested string, // uint128 ) (string, string) { // uint128 x2 - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) caller := std.PrevRealm().Addr() if err := common.AdminOnly(caller); err != nil { @@ -787,8 +787,8 @@ func CollectProtocol( _amount0Requested string, // uint128 _amount1Requested string, // uint128 ) (string, string) { // uint128 x2 - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) caller := std.PrevRealm().Addr() if err := common.GovernanceOnly(caller); err != nil { diff --git a/pool/pool_manager.gno b/pool/pool_manager.gno index 88d48e68..cf318736 100644 --- a/pool/pool_manager.gno +++ b/pool/pool_manager.gno @@ -150,8 +150,8 @@ func CreatePool( // wrap first token0Path, token1Path = poolInfo.wrap() - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) // reinitialize poolInfo with wrapped tokens poolInfo = newPoolParams(token0Path, token1Path, fee, _sqrtPriceX96) @@ -227,8 +227,8 @@ func DoesPoolPathExist(poolPath string) bool { // It constructs the poolPath from the given parameters and returns the corresponding pool. // Returns pool struct func GetPool(token0Path, token1Path string, fee uint32) *Pool { - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) poolPath := GetPoolPath(token0Path, token1Path, fee) pool, exist := pools[poolPath] @@ -258,8 +258,8 @@ func GetPoolFromPoolPath(poolPath string) *Pool { // GetPoolPath generates a poolPath from the given token paths and fee. // The poolPath is constructed by joining the token paths and fee with colons. func GetPoolPath(token0Path, token1Path string, fee uint32) string { - common.MustRegisteredToken(token0Path) - common.MustRegisteredToken(token1Path) + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) // TODO: this check is not unnecessary, if we are sure that // all the token paths in the pool are sorted in alphabetical order. From 16dfe8e459ed90e1dcd05005ad3b4b4d4982ed87 Mon Sep 17 00:00:00 2001 From: 0xTopaz <60733299+onlyhyde@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:32:08 +0900 Subject: [PATCH 17/30] GSW-1838 fix: test errors are fixed (#422) * GSW-1838 fix: test errors are fixed - Integrate helper functions for tests - Change file extensions to prevent test code in the test folder from being executed - Fixing failure errors due to code integration - Known issue : Fixed additional test failure case related to getter * fix: remove time compare in unit test * fix: do not setup data in init * test: pool manger testcase --------- Co-authored-by: n3wbie --- .../__TEST_0_INIT_TOKEN_REGISTER_test.gnoA | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA diff --git a/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA b/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA new file mode 100644 index 00000000..6702bd67 --- /dev/null +++ b/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA @@ -0,0 +1,183 @@ +package pool + +import ( + "std" + "testing" + + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + + "gno.land/r/onbloc/foo" + + "gno.land/r/onbloc/bar" + + "gno.land/r/onbloc/baz" + + "gno.land/r/onbloc/qux" + + "gno.land/r/demo/wugnot" + + "gno.land/r/onbloc/obl" + + "gno.land/r/gnoswap/v1/gns" + + "gno.land/r/gnoswap/v1/consts" + + pusers "gno.land/p/demo/users" +) + +type FooToken struct{} + +func (FooToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return foo.Transfer +} +func (FooToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return foo.TransferFrom +} +func (FooToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return foo.BalanceOf +} +func (FooToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return foo.Approve +} + +type BarToken struct{} + +func (BarToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return bar.Transfer +} +func (BarToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return bar.TransferFrom +} +func (BarToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return bar.BalanceOf +} +func (BarToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return bar.Approve +} + +type BazToken struct{} + +func (BazToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return baz.Transfer +} +func (BazToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return baz.TransferFrom +} +func (BazToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return baz.BalanceOf +} +func (BazToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return baz.Approve +} + +type QuxToken struct{} + +func (QuxToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return qux.Transfer +} +func (QuxToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return qux.TransferFrom +} +func (QuxToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return qux.BalanceOf +} +func (QuxToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return qux.Approve +} + +type WugnotToken struct{} + +func (WugnotToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return wugnot.Transfer +} +func (WugnotToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return wugnot.TransferFrom +} +func (WugnotToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return wugnot.BalanceOf +} +func (WugnotToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return wugnot.Approve +} + +type OBLToken struct{} + +func (OBLToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return obl.Transfer +} +func (OBLToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return obl.TransferFrom +} +func (OBLToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return obl.BalanceOf +} +func (OBLToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return obl.Approve +} + +type GNSToken struct{} + +func (GNSToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return gns.Transfer +} + +func (GNSToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return gns.TransferFrom +} + +func (GNSToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return gns.BalanceOf +} + +func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return gns.Approve +} + +func init() { + std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) + + RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) + RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) + RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) + RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) + RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) + RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) + RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) +} + +func TestGetRegisteredTokens(t *testing.T) { + uassert.Equal(t, len(GetRegisteredTokens()), 7) +} + +func TestRegisterGRC20Interface(t *testing.T) { + uassert.PanicsWithMessage(t, + `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__RegisterGRC20Interface() || only register(g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5) can register token, called from g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm`, + func() { + RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) + }, + ) +} + +func TestUnregisterGRC20Interface(t *testing.T) { + dummy := testutils.TestAddress("dummy") + std.TestSetRealm(std.NewUserRealm(dummy)) + + uassert.PanicsWithMessage(t, + `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__UnregisterGRC20Interface() || unauthorized address(g1v36k6mteta047h6lta047h6lta047h6lz7gmv8) to unregister`, + func() { + UnregisterGRC20Interface("gno.land/r/onbloc/bar") + }, + ) + + uassert.Equal(t, len(GetRegisteredTokens()), 7) + + std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) + UnregisterGRC20Interface("gno.land/r/onbloc/bar") + uassert.Equal(t, len(GetRegisteredTokens()), 6) + + // re-register to avoid panic in other tests + RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) + + std.TestSetRealm(adminRealm) +} From 880311f3479960629571acbbc8ef57eb05bc6d15 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Mon, 2 Dec 2024 19:48:28 +0900 Subject: [PATCH 18/30] GSW-1838 refactor: use grc20reg - use gno's grc20reg realm to support dynamic token transfer in pool --- .../__TEST_0_INIT_TOKEN_REGISTER_test.gnoA | 183 ------------------ 1 file changed, 183 deletions(-) delete mode 100644 pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA diff --git a/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA b/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA deleted file mode 100644 index 6702bd67..00000000 --- a/pool/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA +++ /dev/null @@ -1,183 +0,0 @@ -package pool - -import ( - "std" - "testing" - - "gno.land/p/demo/testutils" - "gno.land/p/demo/uassert" - - "gno.land/r/onbloc/foo" - - "gno.land/r/onbloc/bar" - - "gno.land/r/onbloc/baz" - - "gno.land/r/onbloc/qux" - - "gno.land/r/demo/wugnot" - - "gno.land/r/onbloc/obl" - - "gno.land/r/gnoswap/v1/gns" - - "gno.land/r/gnoswap/v1/consts" - - pusers "gno.land/p/demo/users" -) - -type FooToken struct{} - -func (FooToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return foo.Transfer -} -func (FooToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return foo.TransferFrom -} -func (FooToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return foo.BalanceOf -} -func (FooToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return foo.Approve -} - -type BarToken struct{} - -func (BarToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return bar.Transfer -} -func (BarToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return bar.TransferFrom -} -func (BarToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return bar.BalanceOf -} -func (BarToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return bar.Approve -} - -type BazToken struct{} - -func (BazToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return baz.Transfer -} -func (BazToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return baz.TransferFrom -} -func (BazToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return baz.BalanceOf -} -func (BazToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return baz.Approve -} - -type QuxToken struct{} - -func (QuxToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return qux.Transfer -} -func (QuxToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return qux.TransferFrom -} -func (QuxToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return qux.BalanceOf -} -func (QuxToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return qux.Approve -} - -type WugnotToken struct{} - -func (WugnotToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return wugnot.Transfer -} -func (WugnotToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return wugnot.TransferFrom -} -func (WugnotToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return wugnot.BalanceOf -} -func (WugnotToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return wugnot.Approve -} - -type OBLToken struct{} - -func (OBLToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return obl.Transfer -} -func (OBLToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return obl.TransferFrom -} -func (OBLToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return obl.BalanceOf -} -func (OBLToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return obl.Approve -} - -type GNSToken struct{} - -func (GNSToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return gns.Transfer -} - -func (GNSToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return gns.TransferFrom -} - -func (GNSToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return gns.BalanceOf -} - -func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return gns.Approve -} - -func init() { - std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) -} - -func TestGetRegisteredTokens(t *testing.T) { - uassert.Equal(t, len(GetRegisteredTokens()), 7) -} - -func TestRegisterGRC20Interface(t *testing.T) { - uassert.PanicsWithMessage(t, - `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__RegisterGRC20Interface() || only register(g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5) can register token, called from g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm`, - func() { - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - }, - ) -} - -func TestUnregisterGRC20Interface(t *testing.T) { - dummy := testutils.TestAddress("dummy") - std.TestSetRealm(std.NewUserRealm(dummy)) - - uassert.PanicsWithMessage(t, - `[GNOSWAP-POOL-001] caller has no permission || token_register.gno__UnregisterGRC20Interface() || unauthorized address(g1v36k6mteta047h6lta047h6lta047h6lz7gmv8) to unregister`, - func() { - UnregisterGRC20Interface("gno.land/r/onbloc/bar") - }, - ) - - uassert.Equal(t, len(GetRegisteredTokens()), 7) - - std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - UnregisterGRC20Interface("gno.land/r/onbloc/bar") - uassert.Equal(t, len(GetRegisteredTokens()), 6) - - // re-register to avoid panic in other tests - RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - - std.TestSetRealm(adminRealm) -} From 403bd65b7411ea77de299e6cb94b736bb421da34 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 12:39:02 +0900 Subject: [PATCH 19/30] fix: gno.mod tidy --- pool/gno.mod | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pool/gno.mod b/pool/gno.mod index a4197a6c..3c88fce3 100644 --- a/pool/gno.mod +++ b/pool/gno.mod @@ -1,14 +1 @@ module gno.land/r/gnoswap/v1/pool - -require ( - gno.land/p/demo/json v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/p/gnoswap/int256 v0.0.0-latest - gno.land/p/gnoswap/pool v0.0.0-latest - gno.land/p/gnoswap/uint256 v0.0.0-latest - gno.land/r/gnoswap/v1/common v0.0.0-latest - gno.land/r/gnoswap/v1/consts v0.0.0-latest - gno.land/r/gnoswap/v1/emission v0.0.0-latest - gno.land/r/gnoswap/v1/gns v0.0.0-latest -) From db311cda48bde55685583265240ea0058287789b Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 12:39:21 +0900 Subject: [PATCH 20/30] fix: missing guard logic for HandleWithdrawalFee --- pool/protocol_fee_withdrawal.gno | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pool/protocol_fee_withdrawal.gno b/pool/protocol_fee_withdrawal.gno index bf55e2c2..cacc602c 100644 --- a/pool/protocol_fee_withdrawal.gno +++ b/pool/protocol_fee_withdrawal.gno @@ -46,6 +46,8 @@ func HandleWithdrawalFee( positionCaller std.Address, ) (string, string) { // uint256 x2 common.IsHalted() + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) // only position contract can call this function caller := std.PrevRealm().Addr() From 5e84d81ec5466d41eec34017e02e5b7939654dfa Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 12:40:04 +0900 Subject: [PATCH 21/30] fix: failing testcase --- pool/_helper_test.gno | 117 -------------------------- pool/pool_manager_test.gno | 30 ++++--- pool/protocol_fee_withdrawal_test.gno | 15 ++-- 3 files changed, 24 insertions(+), 138 deletions(-) diff --git a/pool/_helper_test.gno b/pool/_helper_test.gno index ce061a77..5fc7ed5b 100644 --- a/pool/_helper_test.gno +++ b/pool/_helper_test.gno @@ -45,123 +45,6 @@ const ( addr02 = testutils.TestAddress("addr02") ) -type WugnotToken struct{} - -func (WugnotToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return wugnot.Transfer -} -func (WugnotToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return wugnot.TransferFrom -} -func (WugnotToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return wugnot.BalanceOf -} -func (WugnotToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return wugnot.Approve -} - -type GNSToken struct{} - -func (GNSToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return gns.Transfer -} -func (GNSToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return gns.TransferFrom -} -func (GNSToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return gns.BalanceOf -} -func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return gns.Approve -} - -type BarToken struct{} - -func (BarToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return bar.Transfer -} -func (BarToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return bar.TransferFrom -} -func (BarToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return bar.BalanceOf -} -func (BarToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return bar.Approve -} - -type BazToken struct{} - -func (BazToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return baz.Transfer -} -func (BazToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return baz.TransferFrom -} -func (BazToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return baz.BalanceOf -} -func (BazToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return baz.Approve -} - -type FooToken struct{} - -func (FooToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return foo.Transfer -} -func (FooToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return foo.TransferFrom -} -func (FooToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return foo.BalanceOf -} -func (FooToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return foo.Approve -} - -type OBLToken struct{} - -func (OBLToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return obl.Transfer -} -func (OBLToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return obl.TransferFrom -} -func (OBLToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return obl.BalanceOf -} -func (OBLToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return obl.Approve -} - -type QuxToken struct{} - -func (QuxToken) Transfer() func(to pusers.AddressOrName, amount uint64) { - return qux.Transfer -} -func (QuxToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return qux.TransferFrom -} -func (QuxToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return qux.BalanceOf -} -func (QuxToken) Approve() func(spender pusers.AddressOrName, amount uint64) { - return qux.Approve -} - -func init() { - std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - - RegisterGRC20Interface(wugnotPath, WugnotToken{}) - RegisterGRC20Interface(gnsPath, GNSToken{}) - RegisterGRC20Interface(barPath, BarToken{}) - RegisterGRC20Interface(bazPath, BazToken{}) - RegisterGRC20Interface(fooPath, FooToken{}) - RegisterGRC20Interface(oblPath, OBLToken{}) - RegisterGRC20Interface(quxPath, QuxToken{}) -} - var ( admin = pusers.AddressOrName(consts.ADMIN) alice = pusers.AddressOrName(testutils.TestAddress("alice")) diff --git a/pool/pool_manager_test.gno b/pool/pool_manager_test.gno index da1eed7c..0a9776dc 100644 --- a/pool/pool_manager_test.gno +++ b/pool/pool_manager_test.gno @@ -74,13 +74,13 @@ func TestNewPoolParams(t *testing.T) { } func TestGetPoolPath(t *testing.T) { - path := GetPoolPath("tokenA", "tokenB", 500) - expected := "tokenA:tokenB:500" + path := GetPoolPath("gno.land/r/onbloc/bar", "gno.land/r/onbloc/foo", 500) + expected := "gno.land/r/onbloc/bar:gno.land/r/onbloc/foo:500" if path != expected { t.Errorf("Expected path %s, got %s", expected, path) } - path = GetPoolPath("tokenB", "tokenA", 500) + path = GetPoolPath("gno.land/r/onbloc/foo", "gno.land/r/onbloc/bar", 500) if path != expected { t.Errorf("Expected tokens to be sorted, expected %s, got %s", expected, path) } @@ -118,37 +118,37 @@ func TestCreatePool(t *testing.T) { }{ { name: "success - normal token pair", - token0Path: "test/token0", - token1Path: "test/token1", + token0Path: "gno.land/r/onbloc/bar", + token1Path: "gno.land/r/onbloc/foo", fee: 3000, sqrtPrice: "4295128740", }, { name: "fail - same tokens", - token0Path: "test/token0", - token1Path: "test/token0", + token0Path: "gno.land/r/onbloc/bar", + token1Path: "gno.land/r/onbloc/bar", fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, - panicMsg: "[GNOSWAP-POOL-011] same token used in single pool || pool_manager.gno__CreatePool() || expected token0Path(test/token0) != token1Path(test/token0", + panicMsg: "[GNOSWAP-POOL-011] same token used in single pool || pool_manager.gno__CreatePool() || expected token0Path(gno.land/r/onbloc/bar) != token1Path(gno.land/r/onbloc/bar", }, { name: "fail - tokens not in order", - token0Path: "test/tokenB", - token1Path: "test/tokenA", + token0Path: "gno.land/r/onbloc/foo", + token1Path: "gno.land/r/onbloc/bar", fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, - panicMsg: "[GNOSWAP-POOL-012] tokens must be in lexicographical order || pool_manager.gno__CreatePool() || expected token0Path(test/tokenB) < token1Path(test/tokenA)", + panicMsg: "[GNOSWAP-POOL-012] tokens must be in lexicographical order || pool_manager.gno__CreatePool() || expected token0Path(gno.land/r/onbloc/foo) < token1Path(gno.land/r/onbloc/bar)", }, { name: "fail - pool already exists", - token0Path: "test/token0", - token1Path: "test/token1", + token0Path: "gno.land/r/onbloc/bar", + token1Path: "gno.land/r/onbloc/foo", fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, - panicMsg: "[GNOSWAP-POOL-013] pool already created || pool_manager.gno__CreatePool() || expected poolPath(test/token0:test/token1:3000) not to exist", + panicMsg: "[GNOSWAP-POOL-013] pool already created || pool_manager.gno__CreatePool() || expected poolPath(gno.land/r/onbloc/bar:gno.land/r/onbloc/foo:3000) not to exist", }, } @@ -199,4 +199,6 @@ func TestCreatePool(t *testing.T) { } }) } + + resetObject(t) } diff --git a/pool/protocol_fee_withdrawal_test.gno b/pool/protocol_fee_withdrawal_test.gno index 6cbec74e..241459d9 100644 --- a/pool/protocol_fee_withdrawal_test.gno +++ b/pool/protocol_fee_withdrawal_test.gno @@ -1,16 +1,17 @@ package pool import ( + "std" + "strconv" + "strings" + "testing" + "gno.land/p/demo/testutils" "gno.land/p/demo/uassert" pusers "gno.land/p/demo/users" "gno.land/r/demo/users" "gno.land/r/gnoswap/v1/consts" pn "gno.land/r/gnoswap/v1/position" - "std" - "strconv" - "strings" - "testing" ) func TestHandleWithdrawalFee(t *testing.T) { @@ -32,7 +33,7 @@ func TestHandleWithdrawalFee(t *testing.T) { name: "Panic if caller is not position contract", action: func(t *testing.T) { std.TestSetOrigCaller(users.Resolve(admin)) - HandleWithdrawalFee(0, "", "0", "", "0", "", users.Resolve(admin)) + HandleWithdrawalFee(0, "gno.land/r/onbloc/foo", "0", "gno.land/r/onbloc/foo", "0", "", users.Resolve(admin)) }, verify: nil, expected: "[GNOSWAP-POOL-001] caller has no permission || withdrawal_fee.gno__HandleWithdrawalFee() || only position(g1q646ctzhvn60v492x8ucvyqnrj2w30cwh6efk5) can call this function, called from g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d", @@ -45,7 +46,7 @@ func TestHandleWithdrawalFee(t *testing.T) { HandleWithdrawalFee(0, "pkgPath", "1000", "pkgPath", "1000", "poolPath", users.Resolve(admin)) }, verify: nil, - expected: "[GNOSWAP-POOL-002] not registered token || token_register.gno__transferFromByRegisterCall() || token(pkgPath) not registered", + expected: "[GNOSWAP-COMMON-004] token is not registered || token(pkgPath) is not registered", shouldPanic: true, }, { @@ -63,7 +64,7 @@ func TestHandleWithdrawalFee(t *testing.T) { HandleWithdrawalFee(1, wugnotPath, "1000", gnsPath, "1000", poolPath, users.Resolve(alice)) }, verify: nil, - expected: "insufficient allowance", + expected: "[GNOSWAP-POOL-021] token transfer failed || insufficient allowance", shouldPanic: true, }, { From dca84d4b05601cff7dd80c2dac11badac51e3022 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 16:11:08 +0900 Subject: [PATCH 22/30] fix: tc --- pool/position_modify_test.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pool/position_modify_test.gno b/pool/position_modify_test.gno index dec483e6..a6c2da6d 100644 --- a/pool/position_modify_test.gno +++ b/pool/position_modify_test.gno @@ -129,8 +129,8 @@ func TestModifyPositionEdgeCases(t *testing.T) { params.liquidityDelta = i256.MustFromDecimal("-100000000") _, amount0, amount1 := pool.modifyPosition(params) - // remove amount should be negative value of added amount - uassert.Equal(t, amount0.ToString(), "-8040315") - uassert.Equal(t, amount1.ToString(), "-2958014") + // remove amount should be same as added amount + uassert.Equal(t, amount0.ToString(), "8040315") + uassert.Equal(t, amount1.ToString(), "2958014") }) } From de5f079f10dd7fa24b3117f593264d7ab2ce45e8 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 16:11:47 +0900 Subject: [PATCH 23/30] feat: use teller to transfer/transferfrom --- pool/pool.gno | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pool/pool.gno b/pool/pool.gno index 3980adcf..ec96d53d 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -151,12 +151,10 @@ func Collect( var amount0, amount1 *u256.Uint - var amount0, amount1 *u256.Uint - // Smallest of three: amount0Requested, position.tokensOwed0, pool.balances.token0 amount0Req := u256.MustFromDecimal(amount0Requested) amount0, position.tokensOwed0, pool.balances.token0 = collectToken(amount0Req, position.tokensOwed0, pool.balances.token0) - token0 := common.GetToken(pool.token0Path) + token0 := common.GetTokenTeller(pool.token0Path) checkTransferError(token0.Transfer(recipient, amount0.Uint64())) // Smallest of three: amount0Requested, position.tokensOwed0, pool.balances.token0 @@ -166,7 +164,7 @@ func Collect( // Update state first then transfer position.tokensOwed1 = new(u256.Uint).Sub(position.tokensOwed1, amount1) pool.balances.token1 = new(u256.Uint).Sub(pool.balances.token1, amount1) - token1 := common.GetToken(pool.token1Path) + token1 := common.GetTokenTeller(pool.token1Path) checkTransferError(token1.Transfer(recipient, amount1.Uint64())) pool.positions[positionKey] = position @@ -739,8 +737,8 @@ func CollectProtocolByAdmin( token1Path string, fee uint32, recipient std.Address, - _amount0Requested string, // uint128 - _amount1Requested string, // uint128 + amount0Requested string, // uint128 + amount1Requested string, // uint128 ) (string, string) { // uint128 x2 common.MustRegistered(token0Path) common.MustRegistered(token1Path) @@ -784,8 +782,8 @@ func CollectProtocol( token1Path string, fee uint32, recipient std.Address, - _amount0Requested string, // uint128 - _amount1Requested string, // uint128 + amount0Requested string, // uint128 + amount1Requested string, // uint128 ) (string, string) { // uint128 x2 common.MustRegistered(token0Path) common.MustRegistered(token1Path) @@ -897,7 +895,8 @@ func (pool *Pool) transferAndVerify( panic(err) } - transferByRegisterCall(tokenPath, to, amountUint64) + token := common.GetTokenTeller(tokenPath) + checkTransferError(token.Transfer(to, amountUint64)) newBalance, err := updatePoolBalance(token0, token1, absAmount, isToken0) if err != nil { From 89350f80d46052be15b5bc4ca993dbb86695b8c9 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 16:12:09 +0900 Subject: [PATCH 24/30] test: fix mocking old functions --- pool/pool_test.gno | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/pool/pool_test.gno b/pool/pool_test.gno index af02987d..c6ef82d4 100644 --- a/pool/pool_test.gno +++ b/pool/pool_test.gno @@ -6,8 +6,10 @@ import ( "gno.land/p/demo/testutils" "gno.land/p/demo/uassert" + i256 "gno.land/p/gnoswap/int256" u256 "gno.land/p/gnoswap/uint256" + "gno.land/r/gnoswap/v1/consts" ) @@ -576,7 +578,7 @@ func TestTransferFromAndVerify(t *testing.T) { }, from: testutils.TestAddress("from_addr"), to: testutils.TestAddress("to_addr"), - tokenPath: "token0_path", + tokenPath: "gno.land/r/onbloc/bar", amount: i256.NewInt(500), isToken0: true, expectedBal0: u256.NewUint(1500), // 1000 + 500 @@ -592,7 +594,7 @@ func TestTransferFromAndVerify(t *testing.T) { }, from: testutils.TestAddress("from_addr"), to: testutils.TestAddress("to_addr"), - tokenPath: "token1_path", + tokenPath: "gno.land/r/onbloc/foo", amount: i256.NewInt(800), isToken0: false, expectedBal0: u256.NewUint(1000), // unchanged @@ -608,7 +610,7 @@ func TestTransferFromAndVerify(t *testing.T) { }, from: testutils.TestAddress("from_addr"), to: testutils.TestAddress("to_addr"), - tokenPath: "token0_path", + tokenPath: "gno.land/r/onbloc/bar", amount: i256.NewInt(0), isToken0: true, expectedBal0: u256.NewUint(1000), // unchanged @@ -618,13 +620,14 @@ func TestTransferFromAndVerify(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // mock transferFromByRegisterCall - oldTransferFromByRegisterCall := transferFromByRegisterCall - defer func() { transferFromByRegisterCall = oldTransferFromByRegisterCall }() - transferFromByRegisterCall = func(tokenPath string, from, to std.Address, amount uint64) bool { - // mock the transfer (just return true) - return true + oldCheckTransferError := checkTransferError + defer func() { + checkTransferError = oldCheckTransferError + }() + + checkTransferError = func(err error) { + return } tt.pool.transferFromAndVerify(tt.from, tt.to, tt.tokenPath, u256.MustFromDecimal(tt.amount.ToString()), tt.isToken0) @@ -651,18 +654,18 @@ func TestTransferFromAndVerify(t *testing.T) { }, } - oldTransferFromByRegisterCall := transferFromByRegisterCall - defer func() { transferFromByRegisterCall = oldTransferFromByRegisterCall }() + oldCheckTransferError := checkTransferError + defer func() { checkTransferError = oldCheckTransferError }() - transferFromByRegisterCall = func(tokenPath string, from, to std.Address, amount uint64) bool { - return true + checkTransferError = func(err error) { + return } negativeAmount := i256.NewInt(-500) pool.transferFromAndVerify( testutils.TestAddress("from_addr"), testutils.TestAddress("to_addr"), - "token0_path", + "gno.land/r/onbloc/qux", u256.MustFromDecimal(negativeAmount.Abs().ToString()), true, ) @@ -694,7 +697,7 @@ func TestTransferFromAndVerify(t *testing.T) { pool.transferFromAndVerify( testutils.TestAddress("from_addr"), testutils.TestAddress("to_addr"), - "token0_path", + "gno.land/r/onbloc/qux", u256.MustFromDecimal(hugeAmount.ToString()), true, ) From 40f9b722074f8c5929006bad10efd2e4fe19897e Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 19:38:44 +0900 Subject: [PATCH 25/30] test: remove hardcoded value --- pool/pool_manager_test.gno | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pool/pool_manager_test.gno b/pool/pool_manager_test.gno index 0a9776dc..896e4ce2 100644 --- a/pool/pool_manager_test.gno +++ b/pool/pool_manager_test.gno @@ -118,15 +118,15 @@ func TestCreatePool(t *testing.T) { }{ { name: "success - normal token pair", - token0Path: "gno.land/r/onbloc/bar", - token1Path: "gno.land/r/onbloc/foo", + token0Path: barPath, + token1Path: GetPoolFromPoolPath, fee: 3000, sqrtPrice: "4295128740", }, { name: "fail - same tokens", - token0Path: "gno.land/r/onbloc/bar", - token1Path: "gno.land/r/onbloc/bar", + token0Path: barPath, + token1Path: barPath, fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, @@ -134,8 +134,8 @@ func TestCreatePool(t *testing.T) { }, { name: "fail - tokens not in order", - token0Path: "gno.land/r/onbloc/foo", - token1Path: "gno.land/r/onbloc/bar", + token0Path: GetPoolFromPoolPath, + token1Path: barPath, fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, @@ -143,8 +143,8 @@ func TestCreatePool(t *testing.T) { }, { name: "fail - pool already exists", - token0Path: "gno.land/r/onbloc/bar", - token1Path: "gno.land/r/onbloc/foo", + token0Path: barPath, + token1Path: GetPoolFromPoolPath, fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, From 7b61cf9e6e0b792acf7e7a325f0737b59d173217 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 19:39:00 +0900 Subject: [PATCH 26/30] test: detail error message --- .../r/gnoswap/common/grc20reg_helper_test.gno | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno index 023461f1..31c7aa9e 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -16,20 +16,20 @@ var ( ) func TestGetToken(t *testing.T) { - t.Run("registered(by default)", func(t *testing.T) { + t.Run("get regsitered token", func(t *testing.T) { token := GetToken(tokenPath) if token == nil { - t.Error("Expected non-nil teller for foo20") + t.Error("Expected non-nil token for foo20") } }) - t.Run("not registered", func(t *testing.T) { + t.Run("get non registered token", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("Expected panic for non-registered token") } }() - GetToken("not_registered") + GetToken("not_registered_token") }) } @@ -75,20 +75,20 @@ func TestTokenMethod(t *testing.T) { } func TestGetTokenTeller(t *testing.T) { - t.Run("registered(by default)", func(t *testing.T) { + t.Run("get registered token teller", func(t *testing.T) { teller := GetTokenTeller(tokenPath) if teller == nil { t.Error("Expected non-nil teller for foo20") } }) - t.Run("not registered", func(t *testing.T) { + t.Run("get non registered token teller", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("Expected panic for non-registered token") } }() - GetTokenTeller("not_registered") + GetTokenTeller("not_registered_teller") }) } @@ -129,21 +129,21 @@ func TestTellerMethod(t *testing.T) { } func TestIsRegistered(t *testing.T) { - t.Run("registered(by default)", func(t *testing.T) { + t.Run("check if token is registered", func(t *testing.T) { uassert.NoError(t, IsRegistered(tokenPath)) }) - t.Run("not registered", func(t *testing.T) { - uassert.Error(t, IsRegistered("not_registered")) + t.Run("check if token is not registered", func(t *testing.T) { + uassert.Error(t, IsRegistered("not_registered_token")) }) } func TestMustRegistered(t *testing.T) { - t.Run("registered(by default)", func(t *testing.T) { + t.Run("must be registered", func(t *testing.T) { MustRegistered(tokenPath) }) - t.Run("not registered", func(t *testing.T) { + t.Run("panic for non registered token", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Errorf("Expected panic for non-registered token") From 1aa50f60416f435e93985cbf0812f3a7fa5a6ca1 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Tue, 10 Dec 2024 19:42:41 +0900 Subject: [PATCH 27/30] fix: typo --- _deploy/r/gnoswap/common/grc20reg_helper_test.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno index 31c7aa9e..086320ed 100644 --- a/_deploy/r/gnoswap/common/grc20reg_helper_test.gno +++ b/_deploy/r/gnoswap/common/grc20reg_helper_test.gno @@ -85,7 +85,7 @@ func TestGetTokenTeller(t *testing.T) { t.Run("get non registered token teller", func(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Errorf("Expected panic for non-registered token") + t.Errorf("Expected panic for non-registered token teller") } }() GetTokenTeller("not_registered_teller") From c22562621bbc8bd386716876e274e7403fb53b1b Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 11 Dec 2024 12:51:10 +0900 Subject: [PATCH 28/30] remove: duplicate token register check --- pool/pool_manager.gno | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pool/pool_manager.gno b/pool/pool_manager.gno index cf318736..9598bb4f 100644 --- a/pool/pool_manager.gno +++ b/pool/pool_manager.gno @@ -227,9 +227,6 @@ func DoesPoolPathExist(poolPath string) bool { // It constructs the poolPath from the given parameters and returns the corresponding pool. // Returns pool struct func GetPool(token0Path, token1Path string, fee uint32) *Pool { - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - poolPath := GetPoolPath(token0Path, token1Path, fee) pool, exist := pools[poolPath] if !exist { @@ -258,9 +255,6 @@ func GetPoolFromPoolPath(poolPath string) *Pool { // GetPoolPath generates a poolPath from the given token paths and fee. // The poolPath is constructed by joining the token paths and fee with colons. func GetPoolPath(token0Path, token1Path string, fee uint32) string { - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - // TODO: this check is not unnecessary, if we are sure that // all the token paths in the pool are sorted in alphabetical order. if strings.Compare(token1Path, token0Path) < 0 { From 7eab407918c9d737b7d78dccd06b8f83eb0a033a Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 11 Dec 2024 12:58:09 +0900 Subject: [PATCH 29/30] fix: typo --- pool/pool_manager_test.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pool/pool_manager_test.gno b/pool/pool_manager_test.gno index 896e4ce2..328315b5 100644 --- a/pool/pool_manager_test.gno +++ b/pool/pool_manager_test.gno @@ -119,7 +119,7 @@ func TestCreatePool(t *testing.T) { { name: "success - normal token pair", token0Path: barPath, - token1Path: GetPoolFromPoolPath, + token1Path: fooPath, fee: 3000, sqrtPrice: "4295128740", }, @@ -134,7 +134,7 @@ func TestCreatePool(t *testing.T) { }, { name: "fail - tokens not in order", - token0Path: GetPoolFromPoolPath, + token0Path: fooPath, token1Path: barPath, fee: 3000, sqrtPrice: "4295128740", @@ -144,7 +144,7 @@ func TestCreatePool(t *testing.T) { { name: "fail - pool already exists", token0Path: barPath, - token1Path: GetPoolFromPoolPath, + token1Path: fooPath, fee: 3000, sqrtPrice: "4295128740", shouldPanic: true, From 2e656adc31665630b6051aa8b9f1ca2f7f0c22d8 Mon Sep 17 00:00:00 2001 From: 0xTopaz Date: Wed, 11 Dec 2024 13:28:44 +0900 Subject: [PATCH 30/30] refactor: duplicate token register check - GetPoolPath has check function --- pool/pool.gno | 12 ------------ pool/pool_manager.gno | 8 ++++---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/pool/pool.gno b/pool/pool.gno index ec96d53d..4816c6b1 100644 --- a/pool/pool.gno +++ b/pool/pool.gno @@ -28,9 +28,6 @@ func Mint( positionCaller std.Address, ) (string, string) { common.IsHalted() - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.PositionOnly(caller); err != nil { @@ -77,9 +74,6 @@ func Burn( liquidityAmount string, // uint128 ) (string, string) { // uint256 x2 common.IsHalted() - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - caller := std.PrevRealm().Addr() if common.GetLimitCaller() { if err := common.PositionOnly(caller); err != nil { @@ -125,9 +119,6 @@ func Collect( amount1Requested string, ) (string, string) { common.IsHalted() - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.PositionOnly(caller); err != nil { @@ -225,9 +216,6 @@ func Swap( payer std.Address, // router ) (string, string) { common.IsHalted() - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) - if common.GetLimitCaller() { caller := std.PrevRealm().Addr() if err := common.RouterOnly(caller); err != nil { diff --git a/pool/pool_manager.gno b/pool/pool_manager.gno index 9598bb4f..c8f5c25b 100644 --- a/pool/pool_manager.gno +++ b/pool/pool_manager.gno @@ -150,8 +150,7 @@ func CreatePool( // wrap first token0Path, token1Path = poolInfo.wrap() - common.MustRegistered(token0Path) - common.MustRegistered(token1Path) + poolPath := GetPoolPath(token0Path, token1Path, fee) // reinitialize poolInfo with wrapped tokens poolInfo = newPoolParams(token0Path, token1Path, fee, _sqrtPriceX96) @@ -174,8 +173,6 @@ func CreatePool( )) } - poolPath := GetPoolPath(token0Path, token1Path, fee) - // TODO: make this as a parameter prevAddr, prevRealm := getPrev() @@ -255,6 +252,9 @@ func GetPoolFromPoolPath(poolPath string) *Pool { // GetPoolPath generates a poolPath from the given token paths and fee. // The poolPath is constructed by joining the token paths and fee with colons. func GetPoolPath(token0Path, token1Path string, fee uint32) string { + common.MustRegistered(token0Path) + common.MustRegistered(token1Path) + // TODO: this check is not unnecessary, if we are sure that // all the token paths in the pool are sorted in alphabetical order. if strings.Compare(token1Path, token0Path) < 0 {