diff --git a/examples/gno.land/r/x/test_prev/gno.mod b/examples/gno.land/r/x/test_prev/gno.mod new file mode 100644 index 00000000000..de7d5d07e14 --- /dev/null +++ b/examples/gno.land/r/x/test_prev/gno.mod @@ -0,0 +1,8 @@ +module gno.land/r/x/test_prev + +require ( + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest +) diff --git a/examples/gno.land/r/x/test_prev/test_prev.gno b/examples/gno.land/r/x/test_prev/test_prev.gno new file mode 100644 index 00000000000..9466e5f96b9 --- /dev/null +++ b/examples/gno.land/r/x/test_prev/test_prev.gno @@ -0,0 +1,18 @@ +package test_prev + +import ( + "std" + + pusers "gno.land/p/demo/users" + "gno.land/r/demo/foo20" +) + +func DoSomeWithUserBalance() string { + caller := std.GetOrigCaller() + balance := foo20.BalanceOf(pusers.AddressOrName(caller)) + + if balance > 100 { + return "rich user" + } + return "poor user" +} diff --git a/examples/gno.land/r/x/test_prev/test_prev_test.gno b/examples/gno.land/r/x/test_prev/test_prev_test.gno new file mode 100644 index 00000000000..a6b86eafcb6 --- /dev/null +++ b/examples/gno.land/r/x/test_prev/test_prev_test.gno @@ -0,0 +1,32 @@ +package test_prev + +import ( + "std" + "testing" + + "gno.land/r/demo/foo20" +) + +func TestDoSomeWithUserBalancePoor(t *testing.T) { + std.TestSetOrigCaller("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + if DoSomeWithUserBalance() != "poor user" { + t.Error("expected poor user") + } +} + +func TestDoSomeWithUserBalanceRichButPoor(t *testing.T) { + std.TestSetOrigCaller("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + foo20.Faucet() // foo20 will mint tokens to this realm(std.PrevRealm) not user + if DoSomeWithUserBalance() != "poor user" { + t.Error("expected poor user") + } +} + +func TestDoSomeWithUserBalanceRich(t *testing.T) { + std.TestSetPrevAddr("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + + foo20.Faucet() // foo20 will mint tokens to this realm not user + if DoSomeWithUserBalance() != "rich user" { + t.Error("expected rich user") + } +} diff --git a/gnovm/tests/stdlibs/native.go b/gnovm/tests/stdlibs/native.go index 6964a003025..81100838784 100644 --- a/gnovm/tests/stdlibs/native.go +++ b/gnovm/tests/stdlibs/native.go @@ -172,6 +172,48 @@ var nativeFuncs = [...]nativeFunc{ p0) }, }, + { + "std", + "testSetPrevRealm", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{}, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + + testlibs_std.X_testSetPrevRealm( + m, + p0) + }, + }, + { + "std", + "testSetPrevAddr", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{}, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + + testlibs_std.X_testSetPrevAddr( + m, + p0) + }, + }, { "std", "testSetOrigSend", diff --git a/gnovm/tests/stdlibs/std/std.gno b/gnovm/tests/stdlibs/std/std.gno index 2b142634740..0a4f9cc6eff 100644 --- a/gnovm/tests/stdlibs/std/std.gno +++ b/gnovm/tests/stdlibs/std/std.gno @@ -8,6 +8,8 @@ func ClearStoreCache() // injected func TestSetOrigCaller(addr Address) { testSetOrigCaller(string(addr)) } func TestSetOrigPkgAddr(addr Address) { testSetOrigPkgAddr(string(addr)) } +func TestSetPrevRealm(pkgPath string) { testSetPrevRealm(pkgPath) } +func TestSetPrevAddr(addr Address) { testSetPrevAddr(string(addr)) } func TestSetOrigSend(sent, spent Coins) { sentDenom, sentAmt := sent.expandNative() spentDenom, spentAmt := spent.expandNative() @@ -24,6 +26,8 @@ func callerAt(n int) string // native bindings func testSetOrigCaller(s string) func testSetOrigPkgAddr(s string) +func testSetPrevRealm(s string) +func testSetPrevAddr(s string) func testSetOrigSend( sentDenom []string, sentAmt []int64, spentDenom []string, spentAmt []int64) diff --git a/gnovm/tests/stdlibs/std/std.go b/gnovm/tests/stdlibs/std/std.go index f7bc001043e..72a2a7734ed 100644 --- a/gnovm/tests/stdlibs/std/std.go +++ b/gnovm/tests/stdlibs/std/std.go @@ -5,6 +5,8 @@ import ( "strings" "testing" + "github.com/gnolang/gno/gnovm/stdlibs" + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -100,6 +102,21 @@ func X_testSetOrigPkgAddr(m *gno.Machine, addr string) { m.Context = ctx } +func X_testSetPrevRealm(m *gno.Machine, pkgPath string) { + m.Frames[m.NumFrames()-2].LastPackage = &gno.PackageValue{PkgPath: pkgPath} +} + +func X_testSetPrevAddr(m *gno.Machine, addr string) { + // clear all frames to return mocked origin caller + for i := m.NumFrames() - 1; i > 0; i-- { + m.Frames[i].LastPackage = nil + } + + ctx := m.Context.(stdlibs.ExecContext) + ctx.OrigCaller = crypto.Bech32Address(addr) + m.Context = ctx +} + func X_testSetOrigSend(m *gno.Machine, sentDenom []string, sentAmt []int64, spentDenom []string, spentAmt []int64,