From 1f74cc16f7f8b5853fd99ae5181792b985b9db41 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 20 Mar 2024 10:54:23 +0900 Subject: [PATCH 1/4] fix: banker permission --- examples/gno.land/r/demo/wugnot/wugnot.gno | 2 +- .../cmd/gnoland/testdata/issue-1786.txtar | 86 +++++++++++++++++++ gnovm/stdlibs/std/banker.go | 10 ++- 3 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/issue-1786.txtar diff --git a/examples/gno.land/r/demo/wugnot/wugnot.gno b/examples/gno.land/r/demo/wugnot/wugnot.gno index 82c3c43db89..85a05ae3d6d 100644 --- a/examples/gno.land/r/demo/wugnot/wugnot.gno +++ b/examples/gno.land/r/demo/wugnot/wugnot.gno @@ -40,7 +40,7 @@ func Withdraw(amount uint64) { } caller := std.PrevRealm().Addr() - pkgaddr := std.GetOrigPkgAddr() + pkgaddr := std.CurrentRealm().Addr() callerBal, _ := wugnot.BalanceOf(caller) if callerBal < amount { diff --git a/gno.land/cmd/gnoland/testdata/issue-1786.txtar b/gno.land/cmd/gnoland/testdata/issue-1786.txtar new file mode 100644 index 00000000000..c42cca490b6 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/issue-1786.txtar @@ -0,0 +1,86 @@ +# Test for https://github.com/gnolang/gno/issues/1786 + +loadpkg gno.land/r/demo/wugnot + +gnoland start + +# add contract +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/proxywugnot -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! + +# approve wugnot to `proxywugnot ≈ g1fndyg0we60rdfchyy5dwxzkfmhl5u34j932rg3` +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Approve -args "g1fndyg0we60rdfchyy5dwxzkfmhl5u34j932rg3" -args 10000 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! + +# send 10000ugnot to `proxywugnot` to wrap it +gnokey maketx call -pkgpath gno.land/r/demo/proxywugnot --send "10000ugnot" -func ProxyWrap -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! + +# check user's wugnot balance +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func BalanceOf -args "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! +stdout '10000 uint64' + +# unwrap 500 wugnot +gnokey maketx call -pkgpath gno.land/r/demo/proxywugnot -func ProxyUnwrap -args 500 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 + +# XXX without patching anything it will panic +# panic msg: insufficient coins error +# XXX with pathcing only wugnot.gnot it will panic +# panic msg: RealmSendBanker can only send from the realm package address "g1fndyg0we60rdfchyy5dwxzkfmhl5u34j932rg3", but got "g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6" + + +# check user's wugnot balance +gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func BalanceOf -args "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! +stdout '9500 uint64' + +-- gno.mod -- +module gno.land/r/demo/proxywugnot + + +-- realm.gno -- +package proxywugnot + +import ( + "std" + + "gno.land/r/demo/wugnot" + + "gno.land/p/demo/ufmt" +) + +func ProxyWrap() { + sent := std.GetOrigSend() + ugnotSent := uint64(sent.AmountOf("ugnot")) + + if ugnotSent == 0 { + return + } + + // WRAP IT + wugnotAddr := std.DerivePkgAddr("gno.land/r/demo/wugnot") + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins(std.CurrentRealm().Addr(), wugnotAddr, std.Coins{{"ugnot", int64(ugnotSent)}}) + wugnot.Deposit() // `proxywugnot` has ugnot + + // SEND WUGNOT: PROXY_WUGNOT -> USER + wugnot.Transfer(std.GetOrigCaller(), ugnotSent) +} + +func ProxyUnwrap(wugnotAmount uint64) { + if wugnotAmount == 0 { + return + } + userOldWugnot := wugnot.BalanceOf(std.GetOrigCaller()) + + // SEND WUGNOT: USER -> PROXY_WUGNOT + wugnot.TransferFrom(std.GetOrigCaller(), std.CurrentRealm().Addr(), wugnotAmount) + + // UNWRAP IT + wugnot.Withdraw(wugnotAmount) + + // SEND GNOT: PROXY_WUGNOT -> USER + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins(std.CurrentRealm().Addr(), std.GetOrigCaller(), std.Coins{{"ugnot", int64(wugnotAmount)}}) +} \ No newline at end of file diff --git a/gnovm/stdlibs/std/banker.go b/gnovm/stdlibs/std/banker.go index d60efc40819..7d0b339552a 100644 --- a/gnovm/stdlibs/std/banker.go +++ b/gnovm/stdlibs/std/banker.go @@ -44,12 +44,18 @@ func X_bankerSendCoins(m *gno.Machine, bt uint8, fromS, toS string, denoms []str amt := CompactCoins(denoms, amounts) from, to := crypto.Bech32Address(fromS), crypto.Bech32Address(toS) + pkgAddr := ctx.OrigPkgAddr + if m.Realm != nil { + pkgPath := m.Realm.Path + pkgAddr = gno.DerivePkgAddr(pkgPath).Bech32() + } + if bt == btOrigSend || bt == btRealmSend { - if from != ctx.OrigPkgAddr { + if from != pkgAddr { m.Panic(typedString( fmt.Sprintf( "can only send from the realm package address %q, but got %q", - ctx.OrigPkgAddr, from), + pkgAddr, from), )) return } From 5a27bc8128391147a540c84b21fb30b79311be03 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 20 Mar 2024 21:19:53 +0900 Subject: [PATCH 2/4] fix: banktest --- examples/gno.land/r/demo/banktest/banktest.gno | 2 +- examples/gno.land/r/demo/banktest/z_0_filetest.gno | 4 ++-- examples/gno.land/r/demo/banktest/z_1_filetest.gno | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/banktest/banktest.gno b/examples/gno.land/r/demo/banktest/banktest.gno index 29c479dd025..1a23838dcfc 100644 --- a/examples/gno.land/r/demo/banktest/banktest.gno +++ b/examples/gno.land/r/demo/banktest/banktest.gno @@ -40,7 +40,7 @@ func Deposit(returnDenom string, returnAmount int64) string { // return if any. if returnAmount > 0 { banker := std.GetBanker(std.BankerTypeOrigSend) - pkgaddr := std.GetOrigPkgAddr() + pkgaddr := std.CurrentRealm().Addr() // TODO: use std.Coins constructors, this isn't generally safe. banker.SendCoins(pkgaddr, caller, send) return "returned!" diff --git a/examples/gno.land/r/demo/banktest/z_0_filetest.gno b/examples/gno.land/r/demo/banktest/z_0_filetest.gno index 80cb0cf299c..c997d92c53a 100644 --- a/examples/gno.land/r/demo/banktest/z_0_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_0_filetest.gno @@ -10,7 +10,7 @@ import ( ) func main() { - banktestAddr := std.DerivePkgAddr("gno.land/r/banktest") + banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") // print main balance before. mainaddr := std.DerivePkgAddr("main") @@ -21,7 +21,6 @@ func main() { println("main before:", mainbal) // plus OrigSend equals 300. // simulate a Deposit call. - std.TestSetOrigPkgAddr(banktestAddr) std.TestIssueCoins(banktestAddr, std.Coins{{"ugnot", 100000000}}) std.TestSetOrigSend(std.Coins{{"ugnot", 100000000}}, nil) res := banktest.Deposit("ugnot", 100000000) @@ -45,3 +44,4 @@ func main() { // * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 100000000ugnot returned, at 2009-02-13 11:31pm UTC // // ## total deposits +// 300000000ugnot diff --git a/examples/gno.land/r/demo/banktest/z_1_filetest.gno b/examples/gno.land/r/demo/banktest/z_1_filetest.gno index 6b0e8c396dd..3c25a148c35 100644 --- a/examples/gno.land/r/demo/banktest/z_1_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_1_filetest.gno @@ -7,10 +7,9 @@ import ( ) func main() { - banktestAddr := std.DerivePkgAddr("gno.land/r/banktest") + banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") // simulate a Deposit call. - std.TestSetOrigPkgAddr(banktestAddr) std.TestIssueCoins(banktestAddr, std.Coins{{"ugnot", 100000000}}) std.TestSetOrigSend(std.Coins{{"ugnot", 100000000}}, nil) res := banktest.Deposit("ugnot", 101000000) From fd94473e53f0f5b97176479f376a7187b21f28b6 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 20 Mar 2024 21:20:12 +0900 Subject: [PATCH 3/4] fix: faucet --- examples/gno.land/r/gnoland/faucet/faucet.gno | 6 +++--- examples/gno.land/r/gnoland/faucet/faucet_test.gno | 11 ++++------- examples/gno.land/r/gnoland/faucet/z0_filetest.gno | 10 +++++++++- examples/gno.land/r/gnoland/faucet/z1_filetest.gno | 10 +++++++++- examples/gno.land/r/gnoland/faucet/z2_filetest.gno | 8 +++++++- examples/gno.land/r/gnoland/faucet/z3_filetest.gno | 8 +++++++- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/examples/gno.land/r/gnoland/faucet/faucet.gno b/examples/gno.land/r/gnoland/faucet/faucet.gno index c9d8ed503d0..038c7283fa1 100644 --- a/examples/gno.land/r/gnoland/faucet/faucet.gno +++ b/examples/gno.land/r/gnoland/faucet/faucet.gno @@ -43,7 +43,7 @@ func Transfer(to std.Address, send int64) string { gTotalTransfers++ banker := std.GetBanker(std.BankerTypeRealmSend) - pkgaddr := std.GetOrigPkgAddr() + pkgaddr := std.CurrentRealm().Addr() banker.SendCoins(pkgaddr, to, sendCoins) return "" } @@ -54,7 +54,7 @@ func GetPerTransferLimit() int64 { func Render(_ string) string { banker := std.GetBanker(std.BankerTypeRealmSend) - balance := banker.GetCoins(std.GetOrigPkgAddr()) + balance := banker.GetCoins(std.CurrentRealm().Addr()) output := gMessage if gInPause { @@ -65,7 +65,7 @@ func Render(_ string) string { output += ufmt.Sprintf("Balance: %s.\n", balance.String()) output += ufmt.Sprintf("Total transfers: %s (in %d times).\n\n", gTotalTransferred.String(), gTotalTransfers) - output += "Package address: " + std.GetOrigPkgAddr().String() + "\n\n" + output += "Package address: " + std.CurrentRealm().Addr().String() + "\n\n" output += ufmt.Sprintf("Admin: %s\n\n ", gAdminAddr.String()) output += ufmt.Sprintf("Controllers:\n\n ") diff --git a/examples/gno.land/r/gnoland/faucet/faucet_test.gno b/examples/gno.land/r/gnoland/faucet/faucet_test.gno index c1202e09611..1f492adb2dc 100644 --- a/examples/gno.land/r/gnoland/faucet/faucet_test.gno +++ b/examples/gno.land/r/gnoland/faucet/faucet_test.gno @@ -1,7 +1,6 @@ package faucet import ( - "fmt" "std" "testing" @@ -12,7 +11,7 @@ import ( func TestPackage(t *testing.T) { var ( adminaddr = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") - faucetaddr = std.DerivePkgAddr("gno.land/r/faucet") + faucetaddr = std.DerivePkgAddr("gno.land/r/gnoland/faucet") controlleraddr1 = testutils.TestAddress("controller1") controlleraddr2 = testutils.TestAddress("controller2") controlleraddr3 = testutils.TestAddress("controller3") @@ -28,10 +27,8 @@ func TestPackage(t *testing.T) { test1addr = testutils.TestAddress("test1") ) // deposit 1000gnot to faucet contract - std.TestIssueCoins(faucetaddr, std.Coins{{"ugnot", 1000000000}}) - std.TestSetOrigPkgAddr(faucetaddr) - assertBalance(t, faucetaddr, 1000000000) + assertBalance(t, faucetaddr, 1200000000) // by default, balance is empty, and as a user I cannot call Transfer, or Admin commands. @@ -46,7 +43,7 @@ func TestPackage(t *testing.T) { // as an admin, add the controller to contract and deposit more 2000gnot to contract std.TestSetOrigCaller(adminaddr) assertNoErr(t, faucet.AdminAddController(controlleraddr1)) - assertBalance(t, faucetaddr, 1000000000) + assertBalance(t, faucetaddr, 1200000000) // now, send some tokens as controller. std.TestSetOrigCaller(controlleraddr1) @@ -54,7 +51,7 @@ func TestPackage(t *testing.T) { assertBalance(t, test1addr, 1000000) assertNoErr(t, faucet.Transfer(test1addr, 1000000)) assertBalance(t, test1addr, 2000000) - assertBalance(t, faucetaddr, 998000000) + assertBalance(t, faucetaddr, 1198000000) // remove controller // as an admin, remove controller diff --git a/examples/gno.land/r/gnoland/faucet/z0_filetest.gno b/examples/gno.land/r/gnoland/faucet/z0_filetest.gno index d6c3273497f..bcc75897c85 100644 --- a/examples/gno.land/r/gnoland/faucet/z0_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z0_filetest.gno @@ -1,9 +1,17 @@ package main import ( + "std" + "gno.land/r/gnoland/faucet" ) +// mints ugnot to current realm +func init() { + facuetaddr := std.DerivePkgAddr("gno.land/r/gnoland/faucet") + std.TestIssueCoins(facuetaddr, std.Coins{{"ugnot", 200000000}}) +} + // assert render with empty path and no controllers func main() { println(faucet.Render("")) @@ -16,7 +24,7 @@ func main() { // Balance: 200000000ugnot. // Total transfers: (in 0 times). // -// Package address: g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 +// Package address: g1ttrq7mp4zy6dssnmgyyktnn4hcj3ys8xhju0n7 // // Admin: g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 // diff --git a/examples/gno.land/r/gnoland/faucet/z1_filetest.gno b/examples/gno.land/r/gnoland/faucet/z1_filetest.gno index 54fa750ba5e..6afb14b024b 100644 --- a/examples/gno.land/r/gnoland/faucet/z1_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z1_filetest.gno @@ -1,9 +1,17 @@ package main import ( + "std" + "gno.land/r/gnoland/faucet" ) +// mints ugnot to current realm +func init() { + facuetaddr := std.DerivePkgAddr("gno.land/r/gnoland/faucet") + std.TestIssueCoins(facuetaddr, std.Coins{{"ugnot", 200000000}}) +} + // assert render with a path and no controllers func main() { println(faucet.Render("path")) @@ -16,7 +24,7 @@ func main() { // Balance: 200000000ugnot. // Total transfers: (in 0 times). // -// Package address: g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 +// Package address: g1ttrq7mp4zy6dssnmgyyktnn4hcj3ys8xhju0n7 // // Admin: g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 // diff --git a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno index 9b59d7c07d3..054e5329476 100644 --- a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno @@ -7,6 +7,12 @@ import ( "gno.land/r/gnoland/faucet" ) +// mints ugnot to current realm +func init() { + facuetaddr := std.DerivePkgAddr("gno.land/r/gnoland/faucet") + std.TestIssueCoins(facuetaddr, std.Coins{{"ugnot", 200000000}}) +} + // assert render with empty path and 2 controllers func main() { var ( @@ -33,7 +39,7 @@ func main() { // Balance: 200000000ugnot. // Total transfers: (in 0 times). // -// Package address: g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 +// Package address: g1ttrq7mp4zy6dssnmgyyktnn4hcj3ys8xhju0n7 // // Admin: g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 // diff --git a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno index 682a619256a..4a48ca390e2 100644 --- a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno @@ -7,6 +7,12 @@ import ( "gno.land/r/gnoland/faucet" ) +// mints coints to current realm +func init() { + facuetaddr := std.DerivePkgAddr("gno.land/r/gnoland/faucet") + std.TestIssueCoins(facuetaddr, std.Coins{{"ugnot", 200000000}}) +} + // assert render with 2 controllers and 2 transfers func main() { var ( @@ -45,7 +51,7 @@ func main() { // Balance: 197000000ugnot. // Total transfers: 3000000ugnot (in 2 times). // -// Package address: g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 +// Package address: g1ttrq7mp4zy6dssnmgyyktnn4hcj3ys8xhju0n7 // // Admin: g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 // From 9dae5106973f4db35e676abf6907fe5984475737 Mon Sep 17 00:00:00 2001 From: Blake <104744707+r3v4s@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:42:59 +0900 Subject: [PATCH 4/4] docs: update missing link --- docs/concepts/standard-library/coin.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/standard-library/coin.md b/docs/concepts/standard-library/coin.md index 1d79804c6b3..db1618ef3f7 100644 --- a/docs/concepts/standard-library/coin.md +++ b/docs/concepts/standard-library/coin.md @@ -31,6 +31,6 @@ Coins in this set are then available for access by specific types of Bankers, which can manipulate them depending on access rights. [//]: # (TODO ADD LINK TO Effective GNO) -Read more about coins in the [Effective Gno] section. +Read more about coins in the [Effective Gno](https://docs.gno.land/concepts/effective-gno/#native-tokens) section. -The Coin(s) API can be found in under the `std` package [reference](../../reference/standard-library/std/coin.md). \ No newline at end of file +The Coin(s) API can be found in under the `std` package [reference](../../reference/standard-library/std/coin.md).