Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stdlibs/std)!: namespace minted coins with realm path #875

Merged
merged 16 commits into from
May 14, 2024
Merged
79 changes: 79 additions & 0 deletions gno.land/cmd/gnoland/testdata/realm-banker-issued-coin-denom.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# test for https://github.com/gnolang/gno/pull/875

## start a new node
gnoland start

## add realm_banker
gnokey maketx addpkg -pkgdir $WORK/short -pkgpath gno.land/r/test/realm_banker -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1

## add realm_banker with long package_name
gnokey maketx addpkg -pkgdir $WORK/long -pkgpath gno.land/r/test/package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1

## check initial balance
gnokey query bank/balances/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
stdout '"9999996000000ugnot"'

## mint coin from banker
gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Mint -args "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" -args "ugnot" -args "31337" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

## check balance after minting, without patching banker will return '31337ugnot'
thehowl marked this conversation as resolved.
Show resolved Hide resolved
gnokey query bank/balances/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
stdout '"31337/gno.land/r/test/realm_banker:ugnot,9999994000000ugnot"'

## burn coin
gnokey maketx call -pkgpath gno.land/r/test/realm_banker -func Burn -args "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" -args "ugnot" -args "7" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1

## check balance after burning
gnokey query bank/balances/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
stdout '"31330/gno.land/r/test/realm_banker:ugnot,9999992000000ugnot"'

## transfer coin
gnokey maketx send -send "1330/gno.land/r/test/realm_banker:ugnot" -to g1yr0dpfgthph7y6mepdx8afuec4q3ga2lg8tjt0 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1

## check sender balance
gnokey query bank/balances/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
stdout '"30000/gno.land/r/test/realm_banker:ugnot,9999991000000ugnot"'

## check receiver balance
gnokey query bank/balances/g1yr0dpfgthph7y6mepdx8afuec4q3ga2lg8tjt0
stdout '"1330/gno.land/r/test/realm_banker:ugnot"'

## mint coin from long named package with banker
gnokey maketx call -pkgpath gno.land/r/test/package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890 -func Mint -args "g1cq2ecdq3eyn5qa0fzznpurg87zq3k77g63q6u7" -args "ugnot" -args "100" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
gnokey query bank/balances/g1cq2ecdq3eyn5qa0fzznpurg87zq3k77g63q6u7
stdout '"100/gno.land/r/test/package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890:ugnot"'

-- short/realm_banker.gno --
package realm_banker

import (
"std"
)

func Mint(addr std.Address, denom string, amount int64) {
banker := std.GetBanker(std.BankerTypeRealmIssue)
banker.IssueCoin(addr, denom, amount)
}

func Burn(addr std.Address, denom string, amount int64) {
banker := std.GetBanker(std.BankerTypeRealmIssue)
banker.RemoveCoin(addr, denom, amount)
}

-- long/realm_banker.gno --
// package name is 130 characters long
package package89_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_1234567890

import (
"std"
)

func Mint(addr std.Address, denom string, amount int64) {
banker := std.GetBanker(std.BankerTypeRealmIssue)
banker.IssueCoin(addr, denom, amount)
}

func Burn(addr std.Address, denom string, amount int64) {
banker := std.GetBanker(std.BankerTypeRealmIssue)
banker.RemoveCoin(addr, denom, amount)
}
25 changes: 23 additions & 2 deletions gnovm/stdlibs/std/banker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package std

import (
"fmt"
"regexp"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
"github.com/gnolang/gno/tm2/pkg/crypto"
Expand Down Expand Up @@ -88,10 +89,30 @@ func X_bankerTotalCoin(m *gno.Machine, bt uint8, denom string) int64 {

func X_bankerIssueCoin(m *gno.Machine, bt uint8, addr string, denom string, amount int64) {
// gno checks for bt == RealmIssue
m.Context.(ExecContext).Banker.IssueCoin(crypto.Bech32Address(addr), denom, amount)

// check origin denom format
matched, err := regexp.MatchString("[a-z][a-z0-9]{2,15}", denom)
if err != nil || !matched {
m.Panic(typedString("invalid denom format, must be [a-z][a-z0-9]{2,15}"))
return
}
thehowl marked this conversation as resolved.
Show resolved Hide resolved

// Similar to ibc spec
// ibc_denom := 'ibc/' + hash('path' + 'base_denom')
// gno_realm_denom := '/' + 'pkg_path' + ':' + 'base_denom'
newDenom := "/" + m.Realm.Path + ":" + denom
m.Context.(ExecContext).Banker.IssueCoin(crypto.Bech32Address(addr), newDenom, amount)
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

func X_bankerRemoveCoin(m *gno.Machine, bt uint8, addr string, denom string, amount int64) {
// gno checks for bt == RealmIssue
m.Context.(ExecContext).Banker.IssueCoin(crypto.Bech32Address(addr), denom, amount)

matched, err := regexp.MatchString("[a-z][a-z0-9]{2,15}", denom)
if err != nil || !matched {
m.Panic(typedString("invalid denom format, must be [a-z][a-z0-9]{2,15}"))
return
}

newDenom := "/" + m.Realm.Path + ":" + denom
m.Context.(ExecContext).Banker.RemoveCoin(crypto.Bech32Address(addr), newDenom, amount)
}
3 changes: 1 addition & 2 deletions tm2/pkg/std/coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,7 @@ func (coins Coins) Sort() Coins {
// Parsing

var (
// Denominations can be 3 ~ 16 characters long.
reDnmString = `[a-z][a-z0-9]{2,15}`
reDnmString = `[a-z\/][a-z0-9_.:\/]{2,}` // TODO: limit pkg_path length // REF: https://github.com/gnolang/gno/pull/875#discussion_r1543384275
thehowl marked this conversation as resolved.
Show resolved Hide resolved
reAmt = `[[:digit:]]+`
reSpc = `[[:space:]]*`
reDnm = regexp.MustCompile(fmt.Sprintf(`^%s$`, reDnmString))
Expand Down
2 changes: 1 addition & 1 deletion tm2/pkg/std/coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,11 +429,11 @@ func TestParse(t *testing.T) {
{"98 bar , 1 foo ", true, Coins{{"bar", int64(98)}, {"foo", one}}},
{" 55\t \t bling\n", true, Coins{{"bling", int64(55)}}},
{"2foo, 97 bar", true, Coins{{"bar", int64(97)}, {"foo", int64(2)}}},
{"5foo-bar", false, nil},
{"5 mycoin,", false, nil}, // no empty coins in a list
{"2 3foo, 97 bar", false, nil}, // 3foo is invalid coin name
{"11me coin, 12you coin", false, nil}, // no spaces in coin names
{"1.2btc", false, nil}, // amount must be integer
{"5foo-bar", false, nil}, // once more, only letters in coin name
}

for tcIndex, tc := range cases {
Expand Down
Loading