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): restrict Banker methods based on caller of GetBanker #1921

Merged
merged 14 commits into from
Jul 2, 2024
2 changes: 1 addition & 1 deletion docs/concepts/stdlibs/coin.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ which can manipulate them depending on access rights.

Read more about coins in the [Effective Gno](../effective-gno.md#coins) section.

The Coin(s) API can be found in under the `std` package [reference](../../reference/stdlibs/std/coin.md).
The Coin(s) API can be found in under the `std` package [reference](../../reference/stdlibs/std/coin.md).
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/banktest/banktest.gno
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Deposit(returnDenom string, returnAmount int64) string {
// return if any.
if returnAmount > 0 {
banker := std.GetBanker(std.BankerTypeOrigSend)
pkgaddr := std.CurrentRealm().Addr()
pkgaddr := std.GetOrigPkgAddr()
// TODO: use std.Coins constructors, this isn't generally safe.
banker.SendCoins(pkgaddr, caller, send)
return "returned!"
Expand Down
35 changes: 18 additions & 17 deletions examples/gno.land/r/demo/banktest/z_0_filetest.gno
thehowl marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
package main

// NOTE: this doesn't do anything, as it sends to "main".
// SEND: 100000000ugnot

package main

import (
"std"

"gno.land/r/demo/banktest"
)

func main() {
// set up main address and banktest addr.
banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest")

// print main balance before.
mainaddr := std.DerivePkgAddr("main")
std.TestSetOrigCaller(mainaddr)
std.TestSetOrigPkgAddr(banktestAddr)

banker := std.GetBanker(std.BankerTypeReadonly)
// get and print balance of mainaddr.
// with the SEND, + 200 gnot given by the TestContext, main should have 300gnot.
banker := std.GetBanker(std.BankerTypeRealmSend)
mainbal := banker.GetCoins(mainaddr)
println("main before:", mainbal) // plus OrigSend equals 300.
println("main before:", mainbal)

// simulate a Deposit call.
std.TestIssueCoins(banktestAddr, std.Coins{{"ugnot", 100000000}})
std.TestSetOrigSend(std.Coins{{"ugnot", 100000000}}, nil)
res := banktest.Deposit("ugnot", 100000000)
// simulate a Deposit call. use Send + OrigSend to simulate -send.
banker.SendCoins(mainaddr, banktestAddr, std.Coins{{"ugnot", 100_000_000}})
std.TestSetOrigSend(std.Coins{{"ugnot", 100_000_000}}, nil)
res := banktest.Deposit("ugnot", 50_000_000)
println("Deposit():", res)

// print main balance after.
mainbal = banker.GetCoins(mainaddr)
println("main after:", mainbal) // still 300.
println("main after:", mainbal)

// simulate a Render().
// simulate a Render(). banker should have given back all coins.
res = banktest.Render("")
println(res)
}

// Output:
// main before: 200000000ugnot
// main before: 300000000ugnot
// Deposit(): returned!
// main after: 300000000ugnot
// main after: 250000000ugnot
// ## recent activity
//
// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 100000000ugnot returned, at 2009-02-13 11:31pm UTC
// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 50000000ugnot returned, at 2009-02-13 11:31pm UTC
//
// ## total deposits
// 300000000ugnot
// 50000000ugnot
thehowl marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions examples/gno.land/r/demo/banktest/z_1_filetest.gno
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ func main() {
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)
Expand Down
20 changes: 20 additions & 0 deletions examples/gno.land/r/demo/banktest/z_3_filetest.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"std"
)

func main() {
banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest")

mainaddr := std.DerivePkgAddr("main")
std.TestSetOrigCaller(mainaddr)

banker := std.GetBanker(std.BankerTypeRealmSend)
send := std.Coins{{"ugnot", 123}}
banker.SendCoins(banktestAddr, mainaddr, send)

}

// Error:
// can only send coins from realm that created banker "g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4", not "g1dv3435088tlrgggf745kaud0ptrkc9v42k8llz"
32 changes: 13 additions & 19 deletions examples/gno.land/r/demo/wugnot/z0_filetest.gno
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,10 @@ func printBalances() {
printSingleBalance := func(name string, addr std.Address) {
wugnotBal := wugnot.BalanceOf(pusers.AddressOrName(addr))
std.TestSetOrigCaller(addr)
abanker := std.GetBanker(std.BankerTypeOrigSend)
acoins := abanker.GetCoins(addr).AmountOf("ugnot")
bbanker := std.GetBanker(std.BankerTypeRealmIssue)
bcoins := bbanker.GetCoins(addr).AmountOf("ugnot")
cbanker := std.GetBanker(std.BankerTypeRealmSend)
ccoins := cbanker.GetCoins(addr).AmountOf("ugnot")
dbanker := std.GetBanker(std.BankerTypeReadonly)
dcoins := dbanker.GetCoins(addr).AmountOf("ugnot")
fmt.Printf("| %-13s | addr=%s | wugnot=%-5d | ugnot=%-9d %-9d %-9d %-9d |\n",
name, addr, wugnotBal, acoins, bcoins, ccoins, dcoins)
robanker := std.GetBanker(std.BankerTypeReadonly)
coins := robanker.GetCoins(addr).AmountOf("ugnot")
fmt.Printf("| %-13s | addr=%s | wugnot=%-5d | ugnot=%-9d |\n",
name, addr, wugnotBal, coins)
}
println("-----------")
printSingleBalance("wugnot_test", addrt)
Expand All @@ -61,17 +55,17 @@ func printBalances() {

// Output:
// -----------
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=0 | ugnot=200000000 200000000 200000000 200000000 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 |
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=0 | ugnot=200000000 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 |
// -----------
// -----------
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=123400 | ugnot=200000000 200000000 200000000 200000000 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 |
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=123400 | ugnot=200000000 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=100000001 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 |
// -----------
// -----------
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=119158 | ugnot=200004242 200004242 200004242 200004242 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=99995759 99995759 99995759 99995759 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 100000001 100000001 100000001 |
// | wugnot_test | addr=g19rmydykafrqyyegc8uuaxxpzqwzcnxraj2dev9 | wugnot=119158 | ugnot=200004242 |
// | wugnot | addr=g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 | wugnot=0 | ugnot=99995759 |
// | addr1 | addr=g1w3jhxap3ta047h6lta047h6lta047h6l4mfnm7 | wugnot=0 | ugnot=100000001 |
// -----------
26 changes: 23 additions & 3 deletions gnovm/stdlibs/std/banker.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package std

import "strconv"
import (
"strconv"
)

// Realm functions can call std.GetBanker(options) to get
// a banker instance. Banker objects cannot be persisted,
Expand Down Expand Up @@ -66,7 +68,20 @@ func GetBanker(bt BankerType) Banker {
if bt >= maxBanker {
panic("invalid banker type")
}
return banker{bt}

var pkgAddr Address
if bt == BankerTypeOrigSend {
pkgAddr = GetOrigPkgAddr()
if pkgAddr != CurrentRealm().Addr() {
panic("banker with type BankerTypeOrigSend can only be instantiated by the origin package")
}
} else if bt == BankerTypeRealmSend || bt == BankerTypeRealmIssue {
pkgAddr = CurrentRealm().Addr()
}
return banker{
bt,
pkgAddr,
}
}

// These are native bindings to the banker's functions.
Expand All @@ -77,7 +92,8 @@ func bankerIssueCoin(bt uint8, addr string, denom string, amount int64)
func bankerRemoveCoin(bt uint8, addr string, denom string, amount int64)

type banker struct {
bt BankerType
bt BankerType
pkgAddr Address
}

func (b banker) GetCoins(addr Address) (dst Coins) {
Expand All @@ -93,6 +109,10 @@ func (b banker) SendCoins(from, to Address, amt Coins) {
if b.bt == BankerTypeReadonly {
panic("BankerTypeReadonly cannot send coins")
}
if b.pkgAddr != from {
msg := `can only send coins from realm that created banker "` + b.pkgAddr + `", not "` + from + `"`
panic(msg)
}
denoms, amounts := amt.expandNative()
bankerSendCoins(uint8(b.bt), string(from), string(to), denoms, amounts)
}
Expand Down
17 changes: 0 additions & 17 deletions gnovm/stdlibs/std/banker.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,6 @@ 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 != pkgAddr {
m.Panic(typedString(
fmt.Sprintf(
"can only send from the realm package address %q, but got %q",
pkgAddr, from),
))
return
}
}

switch bt {
case btOrigSend:
// indirection allows us to "commit" in a second phase
Expand Down
Loading