From db58dad79f937547d7eb508e148e7745b72ce2a4 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 20 Mar 2024 11:55:01 +0900 Subject: [PATCH 1/6] fix: std.Address validation --- gno.land/cmd/gnoland/testdata/pr-1799.txtar | 12 ++++++++++++ gnovm/stdlibs/std/crypto.gno | 5 +++-- gnovm/stdlibs/stdshim/crypto.gno | 5 +++-- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/pr-1799.txtar diff --git a/gno.land/cmd/gnoland/testdata/pr-1799.txtar b/gno.land/cmd/gnoland/testdata/pr-1799.txtar new file mode 100644 index 00000000000..4a648adba0e --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/pr-1799.txtar @@ -0,0 +1,12 @@ +# Test for https://github.com/gnolang/gno/pull/xxxx +loadpkg gno.land/r/demo/foo20 + +gnoland start + +# execute Faucet +gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Faucet -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout 'OK!' + +# execute Transfer for invalid address +! gnokey maketx call -pkgpath gno.land/r/demo/foo20 -func Transfer -args g1ubwj0apf60hd90txhnh855fkac34rxlsvua0aa -args 1 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stderr '"gnokey" error: --= Error =--\nData: invalid address' \ No newline at end of file diff --git a/gnovm/stdlibs/std/crypto.gno b/gnovm/stdlibs/std/crypto.gno index 8d005dccf5c..b6240a49bc8 100644 --- a/gnovm/stdlibs/std/crypto.gno +++ b/gnovm/stdlibs/std/crypto.gno @@ -6,9 +6,10 @@ func (a Address) String() string { return string(a) } -// IsValid checks if the address is of specific length. Doesn't check prefix or checksum for the address +// IsValid checks if the address is valid bech32 encoded string func (a Address) IsValid() bool { - return len(a) == RawAddressSize*2 // hex length + _, _, ok := decodeBech32(a.String()) + return ok } const RawAddressSize = 20 diff --git a/gnovm/stdlibs/stdshim/crypto.gno b/gnovm/stdlibs/stdshim/crypto.gno index 8d005dccf5c..b6240a49bc8 100644 --- a/gnovm/stdlibs/stdshim/crypto.gno +++ b/gnovm/stdlibs/stdshim/crypto.gno @@ -6,9 +6,10 @@ func (a Address) String() string { return string(a) } -// IsValid checks if the address is of specific length. Doesn't check prefix or checksum for the address +// IsValid checks if the address is valid bech32 encoded string func (a Address) IsValid() bool { - return len(a) == RawAddressSize*2 // hex length + _, _, ok := decodeBech32(a.String()) + return ok } const RawAddressSize = 20 From bcb16d207c99cee5b0240389bf876bda5166a9cc Mon Sep 17 00:00:00 2001 From: n3wbie Date: Wed, 20 Mar 2024 19:59:46 +0900 Subject: [PATCH 2/6] fix: CI fail --- gnovm/stdlibs/std/crypto.gno | 2 +- gnovm/stdlibs/stdshim/crypto.gno | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/stdlibs/std/crypto.gno b/gnovm/stdlibs/std/crypto.gno index b6240a49bc8..402a6af3e22 100644 --- a/gnovm/stdlibs/std/crypto.gno +++ b/gnovm/stdlibs/std/crypto.gno @@ -8,7 +8,7 @@ func (a Address) String() string { // IsValid checks if the address is valid bech32 encoded string func (a Address) IsValid() bool { - _, _, ok := decodeBech32(a.String()) + _, _, ok := DecodeBech32(a) return ok } diff --git a/gnovm/stdlibs/stdshim/crypto.gno b/gnovm/stdlibs/stdshim/crypto.gno index b6240a49bc8..402a6af3e22 100644 --- a/gnovm/stdlibs/stdshim/crypto.gno +++ b/gnovm/stdlibs/stdshim/crypto.gno @@ -8,7 +8,7 @@ func (a Address) String() string { // IsValid checks if the address is valid bech32 encoded string func (a Address) IsValid() bool { - _, _, ok := decodeBech32(a.String()) + _, _, ok := DecodeBech32(a) return ok } From de4fa94acc02dcbe16eb06da1502e6c7f5108e91 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Thu, 21 Mar 2024 11:34:51 +0900 Subject: [PATCH 3/6] fix: foo20 --- examples/gno.land/r/demo/foo20/foo20_test.gno | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/gno.land/r/demo/foo20/foo20_test.gno b/examples/gno.land/r/demo/foo20/foo20_test.gno index 9db0d5f7a6e..eb247535b31 100644 --- a/examples/gno.land/r/demo/foo20/foo20_test.gno +++ b/examples/gno.land/r/demo/foo20/foo20_test.gno @@ -4,13 +4,13 @@ import ( "std" "testing" - "gno.land/p/demo/users" + pusers "gno.land/p/demo/users" + "gno.land/r/demo/users" ) func TestReadOnlyPublicMethods(t *testing.T) { - admin := users.AddressOrName("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") - manfred := users.AddressOrName("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") - unknown := std.Address("g1u0000000000000000000000000000000000000") + admin := pusers.AddressOrName("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") + manfred := pusers.AddressOrName("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") type test struct { name string @@ -25,7 +25,6 @@ func TestReadOnlyPublicMethods(t *testing.T) { {"BalanceOf(admin)", 10000000000, func() uint64 { return BalanceOf(admin) }}, {"BalanceOf(manfred)", 100000000, func() uint64 { return BalanceOf(manfred) }}, {"Allowance(admin, manfred)", 0, func() uint64 { return Allowance(admin, manfred) }}, - {"BalanceOf(unknown)", 0, func() uint64 { return BalanceOf(users.AddressOrName(unknown)) }}, } for _, tc := range tests { if tc.fn() != tc.balance { @@ -34,18 +33,17 @@ func TestReadOnlyPublicMethods(t *testing.T) { } } - // unknown uses the faucet. - std.TestSetOrigCaller(unknown) + // admin uses the faucet. + std.TestSetOrigCaller(users.Resolve(admin)) Faucet() // check balances #2. { tests := []test{ {"TotalSupply", 10110000000, func() uint64 { return TotalSupply() }}, - {"BalanceOf(admin)", 10000000000, func() uint64 { return BalanceOf(admin) }}, + {"BalanceOf(admin)", 10010000000, func() uint64 { return BalanceOf(admin) }}, {"BalanceOf(manfred)", 100000000, func() uint64 { return BalanceOf(manfred) }}, {"Allowance(admin, manfred)", 0, func() uint64 { return Allowance(admin, manfred) }}, - {"BalanceOf(unknown)", 10000000, func() uint64 { return BalanceOf(users.AddressOrName(unknown)) }}, } for _, tc := range tests { if tc.fn() != tc.balance { @@ -68,8 +66,8 @@ func TestErrConditions(t *testing.T) { std.TestSetOrigCaller(admin) { tests := []test{ - {"Transfer(admin, 1)", "cannot send transfer to self", func() { Transfer(users.AddressOrName(admin), 1) }}, - {"Approve(empty, 1))", "invalid address", func() { Approve(users.AddressOrName(empty), 1) }}, + {"Transfer(admin, 1)", "cannot send transfer to self", func() { Transfer(pusers.AddressOrName(admin), 1) }}, + {"Approve(empty, 1))", "invalid address", func() { Approve(pusers.AddressOrName(empty), 1) }}, } for _, tc := range tests { shouldPanicWithMsg(t, tc.fn, tc.msg) From a258319e184ed7777ff7c72a7c036a758f1e71f5 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 22 Mar 2024 10:19:34 +0900 Subject: [PATCH 4/6] chore: rename txtar --- .../testdata/{pr-1799.txtar => grc20-invalid-address.txtar} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename gno.land/cmd/gnoland/testdata/{pr-1799.txtar => grc20-invalid-address.txtar} (91%) diff --git a/gno.land/cmd/gnoland/testdata/pr-1799.txtar b/gno.land/cmd/gnoland/testdata/grc20-invalid-address.txtar similarity index 91% rename from gno.land/cmd/gnoland/testdata/pr-1799.txtar rename to gno.land/cmd/gnoland/testdata/grc20-invalid-address.txtar index 4a648adba0e..da903315333 100644 --- a/gno.land/cmd/gnoland/testdata/pr-1799.txtar +++ b/gno.land/cmd/gnoland/testdata/grc20-invalid-address.txtar @@ -1,4 +1,4 @@ -# Test for https://github.com/gnolang/gno/pull/xxxx +# Test for https://github.com/gnolang/gno/pull/1799 loadpkg gno.land/r/demo/foo20 gnoland start From a6c6a49a6aee302f285fa4b0cd28156fcc723b38 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 22 Mar 2024 10:42:12 +0900 Subject: [PATCH 5/6] test: invalid bech32 address --- gnovm/stdlibs/std/crypto_test.gno | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gnovm/stdlibs/std/crypto_test.gno b/gnovm/stdlibs/std/crypto_test.gno index 293f3e06945..75283c03523 100644 --- a/gnovm/stdlibs/std/crypto_test.gno +++ b/gnovm/stdlibs/std/crypto_test.gno @@ -15,6 +15,17 @@ func TestValid(t *testing.T) { {inputAddress: "g127jydsh6cms3lrtdenydxsckh23a8d6emqcvfa", expected: true}, {inputAddress: "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", expected: true}, {inputAddress: "g14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa", expected: true}, + + // Bech32 doesn't allow '1', 'b', 'i', 'o' for data part + // + // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 + {inputAddress: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", expected: true}, + {inputAddress: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf1", expected: false}, + {inputAddress: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqfb", expected: false}, + {inputAddress: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqfi", expected: false}, + {inputAddress: "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqfo", expected: false}, + + {inputAddress: "g1u0000000000000000000000000000000000000", expected: false}, {inputAddress: "", expected: false}, {inputAddress: "000000000000", expected: false}, {inputAddress: "0000000000000000000000000000000000000000000000000000000000000000000000", expected: false}, From 5e8e93560df0865a5be954124a82f92ede826161 Mon Sep 17 00:00:00 2001 From: n3wbie Date: Fri, 22 Mar 2024 10:54:24 +0900 Subject: [PATCH 6/6] test: unknown-fresh address --- examples/gno.land/r/demo/foo20/foo20_test.gno | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/demo/foo20/foo20_test.gno b/examples/gno.land/r/demo/foo20/foo20_test.gno index eb247535b31..38bdcb333c1 100644 --- a/examples/gno.land/r/demo/foo20/foo20_test.gno +++ b/examples/gno.land/r/demo/foo20/foo20_test.gno @@ -11,6 +11,7 @@ import ( func TestReadOnlyPublicMethods(t *testing.T) { admin := pusers.AddressOrName("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") manfred := pusers.AddressOrName("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") + unknown := pusers.AddressOrName("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // valid but never used. type test struct { name string @@ -25,6 +26,7 @@ func TestReadOnlyPublicMethods(t *testing.T) { {"BalanceOf(admin)", 10000000000, func() uint64 { return BalanceOf(admin) }}, {"BalanceOf(manfred)", 100000000, func() uint64 { return BalanceOf(manfred) }}, {"Allowance(admin, manfred)", 0, func() uint64 { return Allowance(admin, manfred) }}, + {"BalanceOf(unknown)", 0, func() uint64 { return BalanceOf(unknown) }}, } for _, tc := range tests { if tc.fn() != tc.balance { @@ -33,17 +35,18 @@ func TestReadOnlyPublicMethods(t *testing.T) { } } - // admin uses the faucet. - std.TestSetOrigCaller(users.Resolve(admin)) + // unknown uses the faucet. + std.TestSetOrigCaller(users.Resolve(unknown)) Faucet() // check balances #2. { tests := []test{ {"TotalSupply", 10110000000, func() uint64 { return TotalSupply() }}, - {"BalanceOf(admin)", 10010000000, func() uint64 { return BalanceOf(admin) }}, + {"BalanceOf(admin)", 10000000000, func() uint64 { return BalanceOf(admin) }}, {"BalanceOf(manfred)", 100000000, func() uint64 { return BalanceOf(manfred) }}, {"Allowance(admin, manfred)", 0, func() uint64 { return Allowance(admin, manfred) }}, + {"BalanceOf(unknown)", 10000000, func() uint64 { return BalanceOf(unknown) }}, } for _, tc := range tests { if tc.fn() != tc.balance {