-
Notifications
You must be signed in to change notification settings - Fork 382
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
fix(stdlibs/std): Banker should only send coins owned by the calling realm #1787
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a valid testing case, why do we remove this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a valid testing case, why do we modify this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
std.TestIssueCoins(banktestAddr, std.Coins{{"ugnot", 100000000}}) | ||
std.TestSetOrigSend(std.Coins{{"ugnot", 100000000}}, nil) | ||
res := banktest.Deposit("ugnot", 101000000) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,7 +43,7 @@ func Transfer(to std.Address, send int64) string { | |
gTotalTransfers++ | ||
|
||
banker := std.GetBanker(std.BankerTypeRealmSend) | ||
pkgaddr := std.GetOrigPkgAddr() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we make this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. banker type used here is 'RealmSend', not 'OrigSend' |
||
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 ") | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems opposite. g1pf6dv9fjk3rn0m4jjcne306ga4he3mzmupfjl6 is the address of gno.land/r/demo/wugnot There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Above msg happens(panics) when calling 'proxywugnot.Unwrap()' without patching banker.go So we expect 'proxywugnot' (g1f) to send its own coin, not from 'wugnot' (g1p) |
||
|
||
|
||
# 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)}}) | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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 { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The earlier code checks against the package address for SendCoins() in the OrigSendBanker and RealmSendBanker separately. gno/gnovm/stdlibs/std/banker.go Line 97 in 6c5b4cf
gno/gnovm/stdlibs/std/banker.go Line 144 in 6c5b4cf
The code is the same, but the state of the package address in different banker instances could be different. In the current code, it is merged into one logic, where it checks either OrigPkgAddr or m.Realm.Path for SendCoin() of both OrigSendBanker and RealmSendBanker together. However, these should be checked separately. If not, other places that require checking OriginSendBanker's OrigPkgAddr might fail when ctx.OrignPkgAddr and m.Realm.PathAddr have different values. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looking into this // UPDATE |
||||||
m.Panic(typedString( | ||||||
fmt.Sprintf( | ||||||
"can only send from the realm package address %q, but got %q", | ||||||
ctx.OrigPkgAddr, from), | ||||||
pkgAddr, from), | ||||||
)) | ||||||
return | ||||||
} | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we modify this testing case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2ae3865