From d1a5e113c8b06403eea3aee2f7ae354fa323c937 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Thu, 26 Dec 2024 14:58:04 +0900 Subject: [PATCH] refactor: use `grc20reg` realm to support multiple grc20 tokens - replaces previous token_register pattern --- router/_helper_test.gno | 141 ------------------------ router/exact_in_test.gno | 11 +- router/protocol_fee_swap.gno | 3 +- router/protocol_fee_swap_test.gno | 20 +--- router/router_test.gno | 60 +---------- router/swap_inner.gno | 6 +- router/token_register.gno | 172 ------------------------------ 7 files changed, 13 insertions(+), 400 deletions(-) delete mode 100644 router/token_register.gno diff --git a/router/_helper_test.gno b/router/_helper_test.gno index 55a61b514..c20edaf64 100644 --- a/router/_helper_test.gno +++ b/router/_helper_test.gno @@ -20,17 +20,6 @@ import ( "gno.land/r/onbloc/qux" ) -func init() { - std.TestSetRealm(std.NewUserRealm("g1er355fkjksqpdtwmhf5penwa82p0rhqxkkyhk5")) - RegisterGRC20Interface(wugnotPath, WugnotToken{}) - RegisterGRC20Interface(gnsPath, GNSToken{}) - RegisterGRC20Interface(barPath, BarToken{}) - RegisterGRC20Interface(bazPath, BazToken{}) - RegisterGRC20Interface(fooPath, FooToken{}) - RegisterGRC20Interface(oblPath, OBLToken{}) - RegisterGRC20Interface(quxPath, QuxToken{}) -} - const ( ugnotDenom string = "ugnot" ugnotPath string = "ugnot" @@ -78,136 +67,6 @@ var ( maxTick int32 = 887220 ) -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)) -} - var ( admin = pusers.AddressOrName(consts.ADMIN) adminAddr = users.Resolve(admin) diff --git a/router/exact_in_test.gno b/router/exact_in_test.gno index 8b14d4587..831e71f86 100644 --- a/router/exact_in_test.gno +++ b/router/exact_in_test.gno @@ -3,9 +3,11 @@ package router import ( "std" "testing" - "time" "gno.land/r/gnoswap/v1/consts" + + "gno.land/r/onbloc/bar" + "gno.land/r/onbloc/baz" ) func TestExactInSwapRouteOperation_Validate(t *testing.T) { @@ -96,9 +98,6 @@ func TestExactInSwapRoute(t *testing.T) { user1Realm := std.NewUserRealm(user1Addr) std.TestSetRealm(user1Realm) - bar := BarToken{} - baz := BazToken{} - tests := []struct { name string setup func() @@ -113,8 +112,8 @@ func TestExactInSwapRoute(t *testing.T) { { name: "BAR -> BAZ", setup: func() { - bar.Approve()(a2u(consts.ROUTER_ADDR), maxApprove) - baz.Approve()(a2u(consts.ROUTER_ADDR), maxApprove) + bar.Approve(a2u(consts.ROUTER_ADDR), maxApprove) + baz.Approve(a2u(consts.ROUTER_ADDR), maxApprove) TokenFaucet(t, barPath, a2u(user1Addr)) }, inputToken: barPath, diff --git a/router/protocol_fee_swap.gno b/router/protocol_fee_swap.gno index 0098edbbe..a122b9f75 100644 --- a/router/protocol_fee_swap.gno +++ b/router/protocol_fee_swap.gno @@ -31,7 +31,8 @@ func handleSwapFee( feeAmount.Div(feeAmount, u256.NewUint(10000)) feeAmountUint64 := feeAmount.Uint64() - transferFromByRegisterCall(outputToken, std.PrevRealm().Addr(), consts.PROTOCOL_FEE_ADDR, feeAmountUint64) + outputTeller := common.GetTokenTeller(outputToken) + outputTeller.TransferFrom(std.PrevRealm().Addr(), consts.PROTOCOL_FEE_ADDR, feeAmountUint64) prevAddr, prevRealm := getPrev() diff --git a/router/protocol_fee_swap_test.gno b/router/protocol_fee_swap_test.gno index c008fafbb..372123e63 100644 --- a/router/protocol_fee_swap_test.gno +++ b/router/protocol_fee_swap_test.gno @@ -3,28 +3,10 @@ package router import ( "testing" - pusers "gno.land/p/demo/users" - u256 "gno.land/p/gnoswap/uint256" ) func TestHandleSwapFee(t *testing.T) { - token0 := "token0" - - mockToken := &struct { - GRC20Interface - }{ - GRC20Interface: MockGRC20{ - TransferFn: func(to pusers.AddressOrName, amount uint64) {}, - TransferFromFn: func(from, to pusers.AddressOrName, amount uint64) {}, - BalanceOfFn: func(owner pusers.AddressOrName) uint64 { return 1000000 }, - ApproveFn: func(spender pusers.AddressOrName, amount uint64) {}, - }, - } - - registerGRC20ForTest(t, token0, mockToken) - defer unregisterGRC20ForTest(t, token0) - tests := []struct { name string amount *u256.Uint @@ -65,7 +47,7 @@ func TestHandleSwapFee(t *testing.T) { swapFee = originalSwapFee }() - result := handleSwapFee(token0, tt.amount) + result := handleSwapFee(barPath, tt.amount) if !result.Eq(tt.expectedAmount) { t.Errorf("handleSwapFee() = %v, want %v", result, tt.expectedAmount) diff --git a/router/router_test.gno b/router/router_test.gno index 98df2af3b..a11a7cb8f 100644 --- a/router/router_test.gno +++ b/router/router_test.gno @@ -2,71 +2,13 @@ package router import ( "std" - "strconv" - "strings" - "testing" - - "gno.land/p/demo/uassert" - "gno.land/p/demo/testutils" + "testing" "gno.land/r/gnoswap/v1/consts" - i256 "gno.land/p/gnoswap/int256" - u256 "gno.land/p/gnoswap/uint256" pl "gno.land/r/gnoswap/v1/pool" - pn "gno.land/r/gnoswap/v1/position" - "gno.land/r/demo/wugnot" - "gno.land/r/onbloc/bar" - "gno.land/r/onbloc/baz" - "gno.land/r/onbloc/qux" - "gno.land/r/gnoswap/v1/gns" - - pusers "gno.land/p/demo/users" ) -func registerGRC20ForTest(t *testing.T, pkgPath string, igrc20 GRC20Interface) { - t.Helper() - registered[pkgPath] = igrc20 -} - -func unregisterGRC20ForTest(t *testing.T, pkgPath string) { - t.Helper() - delete(registered, pkgPath) -} - -type MockGRC20 struct { - TransferFn func(to pusers.AddressOrName, amount uint64) - TransferFromFn func(from, to pusers.AddressOrName, amount uint64) - BalanceOfFn func(owner pusers.AddressOrName) uint64 - ApproveFn func(spender pusers.AddressOrName, amount uint64) - AllowanceFn func(owner, spender pusers.AddressOrName) uint64 -} - -func (m MockGRC20) Transfer() func(to pusers.AddressOrName, amount uint64) { - return m.TransferFn -} - -func (m MockGRC20) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { - return m.TransferFromFn -} - -func (m MockGRC20) BalanceOf() func(owner pusers.AddressOrName) uint64 { - return m.BalanceOfFn -} - -func (m MockGRC20) Approve() func(spender pusers.AddressOrName, amount uint64) { - return m.ApproveFn -} - -func (m MockGRC20) Allowance() func(owner, spender pusers.AddressOrName) uint64 { - if m.AllowanceFn != nil { - return m.AllowanceFn - } - return func(owner, spender pusers.AddressOrName) uint64 { - return 1000000000000 - } -} - func setupTestPool( t *testing.T, token0Path, token1Path string, diff --git a/router/swap_inner.gno b/router/swap_inner.gno index ac7c7a3f4..a9411240f 100644 --- a/router/swap_inner.gno +++ b/router/swap_inner.gno @@ -42,8 +42,10 @@ func swapInner( sqrtPriceLimitX96 = calculateSqrtPriceLimitForSwap(zeroForOne, data.fee, sqrtPriceLimitX96) // ROUTER approves POOL as spender - approveByRegisterCall(data.tokenIn, consts.POOL_ADDR, consts.UINT64_MAX) - approveByRegisterCall(data.tokenOut, consts.POOL_ADDR, consts.UINT64_MAX) + tokenIn := common.GetTokenTeller(data.tokenIn) + tokenOut := common.GetTokenTeller(data.tokenOut) + tokenIn.Approve(consts.POOL_ADDR, consts.UINT64_MAX) + tokenOut.Approve(consts.POOL_ADDR, consts.UINT64_MAX) amount0Str, amount1Str := pl.Swap( // int256, int256 data.tokenIn, diff --git a/router/token_register.gno b/router/token_register.gno deleted file mode 100644 index ee68bccad..000000000 --- a/router/token_register.gno +++ /dev/null @@ -1,172 +0,0 @@ -package router - -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) - locked = false // mutex -) - -// 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(err) - } - - caller := std.PrevRealm().Addr() - if err := common.TokenRegisterOnly(caller); err != nil { - panic(err) - } - - 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), - )) - } - - if !locked { - locked = true - registered[pkgPath].Transfer()(pusers.AddressOrName(to), amount) - - defer func() { - locked = false - }() - } else { - panic(addDetailToError( - errLocked, - ufmt.Sprintf("token_register.gno__transferByRegisterCall() || expected locked(%t) to be false", locked), - )) - } - - 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), - )) - } - - if !locked { - locked = true - registered[pkgPath].TransferFrom()(pusers.AddressOrName(from), pusers.AddressOrName(to), amount) - - defer func() { - locked = false - }() - } else { - panic(addDetailToError( - errLocked, - ufmt.Sprintf("token_register.gno__transferFromByRegisterCall() || expected locked(%t) to be false", locked), - )) - } - 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 -}