Transaction
A32002B497EEA7…BD77BF985E0A
Block 77,249 · index 1 · indexed
Summary
- Hash
- A32002B497EEA74E267CAFF6749B205F6B7D493AB4EB75244482BD77BF985E0A
- Block
- 77,249
- Size
- 9749 bytes
- Gas used
- 17,560,973 / 21,073,132
- Fee
- 21074ugnot
- Status
- success
Messages
- Package
- gno.land/r/gnoswap/common/v1
Arguments · 17
- #1common
- #2errors.gno
- #3package common import ( "gno.land/p/nt/ufmt/v0" ) const ( errNotRegistered = "[GNOSWAP-COMMON-001] token is not registered" errNotHandleNativeCoin = "[GNOSWAP-COMMON-002] handle native coin is not allowed" errInvalidTokenKey = "[GNOSWAP-COMMON-003] invalid token key" ) func newErrorWithDetail(message string, detail string) string { return ufmt.Errorf("%s || %s", message, detail).Error() }
- #4gnomod.toml
- #5module = "gno.land/r/gnoswap/common/v1" gno = "0.9"
- #6init.gno
- #7package common import ( "gno.land/r/gnoswap/common" ) func init(cur realm) { registerCommonV1(cur) } func registerCommonV1(cur realm) { common.RegisterInitializer(cross(cur), func(_ int, rlm realm) common.ICommon { return NewCommonV1() }) }
- #8instance.gno
- #9package common import ( "errors" "gno.land/p/nt/grc20/v0" "gno.land/p/nt/ufmt/v0" "gno.land/r/gnoswap/common" "gno.land/r/nt/grc20reg/v0" ) // commonV1 executes token operations against gno.land/r/nt/grc20reg/v0. type commonV1 struct{} // NewCommonV1 returns the common implementation backed by the registered GRC20 // token registry. // // Returns: // - implementation: new ICommon implementation instance func NewCommonV1() common.ICommon { return &commonV1{} } // IsRegistered verifies that tokenKey is valid and resolves to a registered // GRC20 token. // // Parameters: // - tokenKey: registry key identifying the token, including its realm path and symbol // // Returns: // - error: nil when the key is valid and registered; an error when validation // fails or no token is registered under the key func (c *commonV1) IsRegistered(tokenKey string) error { if err := validateTokenKey(tokenKey); err != nil { return err } if grc20reg.Get(tokenKey) == nil { return ufmt.Errorf("token(%s) is not registered", tokenKey) } return nil } // ValidateRegistered verifies every supplied token key before a multi-token // operation proceeds. // // Parameters: // - tokenKeys: token registry keys that must all be valid and registered // // Returns: // - error: nil when every key is registered; an error identifying the first // key that is invalid or unregistered otherwise func (c *commonV1) ValidateRegistered(tokenKeys ...string) error { for _, tokenKey := range tokenKeys { if err := c.IsRegistered(tokenKey); err != nil { return errors.New(newErrorWithDetail( errNotRegistered, ufmt.Sprintf("token(%s)", tokenKey), )) } } return nil } // TotalSupply returns the total supply recorded for a registered token. // // Parameters: // - tokenKey: registry key of the token to inspect // // Returns: // - supply: token total supply; panics when tokenKey is invalid or unregistered func (c *commonV1) TotalSupply(tokenKey string) int64 { return c.mustGetToken(tokenKey).TotalSupply() } // BalanceOf returns the token balance held by addr. // // Parameters: // - tokenKey: registry key of the token to inspect // - addr: address whose token balance is queried // // Returns: // - balance: amount of tokenKey held by addr; panics when tokenKey is invalid // or unregistered func (c *commonV1) BalanceOf(tokenKey string, addr address) int64 { return c.mustGetToken(tokenKey).BalanceOf(addr) } // Allowance returns the amount that spender may transfer from owner. // // Parameters: // - tokenKey: registry key of the token to inspect // - owner: address that granted the allowance // - spender: address authorized to spend from owner // // Returns: // - allowance: remaining token amount spender may transfer; panics when // tokenKey is invalid or unregistered func (c *commonV1) Allowance(tokenKey string, owner, spender address) int64 { return c.mustGetToken(tokenKey).Allowance(owner, spender) } // Transfer moves amount of a registered token to to using a teller bound to rlm. // // Parameters: // - _: realm-call discriminator; callers pass 0 // - rlm: propagated realm context used to bind the token teller and forwarded // for the token actor's realm validation // - tokenKey: registry key of the token to transfer // - to: recipient address // - amount: number of token units to transfer // // Returns: // - error: nil after a successful transfer; the token teller's validation or // transfer error otherwise func (c *commonV1) Transfer(_ int, rlm realm, tokenKey string, to address, amount int64) error { return c.getTokenTeller(0, rlm, tokenKey).Transfer(0, rlm, to, amount) } // TransferFrom moves amount of a registered token from from to to using the // allowance/authorization associated with the calling realm. // // Parameters: // - _: realm-call discriminator; callers pass 0 // - rlm: propagated realm context used to bind the token teller and forwarded // for the token actor's realm validation // - tokenKey: registry key of the token to transfer // - from: address whose token balance is debited // - to: recipient address // - amount: number of token units to transfer // // Returns: // - error: nil after a successful transfer; the token teller's validation, // allowance, or balance error otherwise func (c *commonV1) TransferFrom(_ int, rlm realm, tokenKey string, from, to address, amount int64) error { return c.getTokenTeller(0, rlm, tokenKey).TransferFrom(0, rlm, from, to, amount) } // Approve sets amount as the allowance that spender may use from the caller. // // Parameters: // - _: realm-call discriminator; callers pass 0 // - rlm: propagated realm context used to bind the token teller and forwarded // for the token actor's realm validation // - tokenKey: registry key of the token to approve // - spender: address authorized to spend // - amount: maximum number of token units spender may transfer // // Returns: // - error: nil after the allowance is stored; the token teller's validation // error otherwise func (c *commonV1) Approve(_ int, rlm realm, tokenKey string, spender address, amount int64) error { return c.getTokenTeller(0, rlm, tokenKey).Approve(0, rlm, spender, amount) } func (c *commonV1) mustGetToken(tokenKey string) *grc20.Token { if err := validateTokenKey(tokenKey); err != nil { panic(err.Error()) } token := grc20reg.Get(tokenKey) if token == nil { panic(newErrorWithDetail(errNotRegistered, ufmt.Sprintf("unknown token(%s)", tokenKey))) } return token } // getTokenTeller binds the token actor to rlm. This is a same-realm borrow, // so rlm stays current and the actor is the calling realm. func (c *commonV1) getTokenTeller(_ int, rlm realm, tokenKey string) grc20.Teller { return c.mustGetToken(tokenKey).RealmTeller(0, rlm) }
- #10native_coin.gno
- #11package common import ( "chain/runtime/unsafe" "errors" ) // ValidateNotHandleNativeCoin rejects calls that include native coins in the // transaction's origin send data; it returns nil when no native coin is attached. // // Returns: // - error: non-nil when the call attempts to send native coins; nil otherwise func (c *commonV1) ValidateNotHandleNativeCoin() error { if len(unsafe.OriginSend()) > 0 { return errors.New(errNotHandleNativeCoin) } return nil }
- #12render.gno
- #13package common import ( "chain" "strings" "gno.land/p/moul/md/v0" "gno.land/p/moul/mdtable/v0" "gno.land/p/nt/ufmt/v0" "gno.land/r/gnoswap/common" "gno.land/r/nt/grc20reg/v0" ) func (c *commonV1) Render(path string) string { if path != "" { return "404\n" } implementation := common.GetImplementationPackagePath() table := mdtable.Table{ Headers: []string{"Field", "Value"}, Rows: [][]string{ {"Realm address", md.InlineCode(chain.PackageAddress("gno.land/r/gnoswap/common").String())}, {"Active implementation", md.Link(implementation, strings.TrimPrefix(implementation, "gno.land"))}, {"Token registry", md.Link("gno.land/r/nt/grc20reg/v0", "/r/nt/grc20reg/v0")}, {"Registry entries (network-wide)", ufmt.Sprintf("%d", grc20reg.GetRegistry().Size())}, }, } out := md.H1("Gnoswap Common") + "\n" out += md.H2("Registry configuration") + "\n" out += table.String() + "\n" out += md.Paragraph( "Token operations resolve a registered " + md.InlineCode("realm-path.SYMBOL") + " key. " + "The registry count includes tokens outside Gnoswap; it is not a trading whitelist.", ) out += md.Paragraph( "Native coins are not accepted by token operations. " + "Query balances and allowances per token; amounts use that token's base units.", ) return out }
- #14validate.gno
- #15package common import ( "errors" "gno.land/p/nt/ufmt/v0" ) // Token keys ("<realm path>.<SYMBOL>") are embedded verbatim in pool paths // ("<key0>:<key1>:<fee>") and router routes ("<pool>*POOL*<pool>,<route>"), // so the key charset is an allowlist rather than a blocklist of separators: // package-path characters plus '.' plus the GRC20 symbol charset. func isTokenKeyChar(c rune) bool { switch { case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9': return true case c == '_', c == '-', c == '.', c == '/': return true } return false } func validateTokenKey(tokenKey string) error { if tokenKey == "" { return errors.New(newErrorWithDetail(errInvalidTokenKey, "empty token key")) } for _, ch := range tokenKey { if !isTokenKeyChar(ch) { return errors.New(newErrorWithDetail( errInvalidTokenKey, ufmt.Sprintf("token key(%s) contains %q", tokenKey, string(ch)), )) } } return nil }
- #16/gno.MemPackageType
- #17 MPUserAll
Result log
msg:0,success:true,log:,events:[]