z5ad_transfer_voucher_native_coins_filetest.gno
5.68 Kb · 139 lines
1// PKGPATH: gno.land/r/aib/main
2package main
3
4// Regression test: an IBC voucher Transfer that attaches native coins via the
5// tx send field must be rejected, mirroring the guard the GRC20 branch already
6// enforces. The voucher GRC20 token is burnt in OnSendPacket, so any native
7// coins sent alongside would be stuck at this realm.
8//
9// The voucher transfer is otherwise valid here (direct user call, existing
10// voucher, sufficient balance), so the only reason it fails is the attached
11// native coins.
12
13import (
14 "chain"
15 "encoding/hex"
16 "testing"
17 "time"
18
19 tmtesting "gno.land/p/aib/ibc/lightclient/tendermint/testing"
20 "gno.land/p/aib/ibc/types"
21
22 "gno.land/p/aib/ics23"
23 "gno.land/r/aib/ibc/apps/transfer"
24 "gno.land/r/aib/ibc/core"
25)
26
27func main(cur realm) {
28 var (
29 chainID = "chain-id-2"
30 trustedHeight = types.NewHeight(2, 2)
31 clientState = tmtesting.NewClientState(chainID, trustedHeight)
32 apphash, _ = hex.DecodeString("0eadf50c7992d8e1366b8ea63ab7d1346de4762c3d449764ef7dc404ba48381f")
33 trustedValset = tmtesting.GenValset()
34 consensusState = tmtesting.GenConsensusState(time.Now(), apphash, trustedValset.Hash())
35 counterpartyID = "07-tendermint-42"
36 )
37 clientID := core.CreateClient(cross(cur), clientState, consensusState)
38 core.RegisterCounterparty(cross(cur), clientID, [][]byte{[]byte("iavlStoreKey"), []byte("prefix2")}, counterpartyID)
39
40 // The voucher owner is the signing EOA (OriginCaller). RecvPacket mints 100
41 // vouchers to it so the balance is non-zero.
42 owner := cur.Previous().Address()
43 recvPacket(cur, clientID, counterpartyID, trustedHeight, owner)
44
45 // ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8
46 voucherDenom := transfer.NewDenom("uphoton", transfer.NewHop(transfer.PortID, clientID)).IBCDenom()
47 println("\nvoucher balance before:", transfer.VoucherBalanceOf(voucherDenom, owner))
48
49 // Direct user call so the IsUserCall guard passes, but native coins are
50 // attached to the tx. The guard must reject the transfer before any voucher
51 // is burnt.
52 testing.SetRealm(testing.NewUserRealm(owner))
53 testing.SetOriginSend(chain.NewCoins(chain.NewCoin("ugnot", 100)))
54 transfer.Transfer(cross(cur), clientID, "atone1user", voucherDenom, 100, uint64(time.Now().Add(time.Hour).Unix()), "memo")
55
56 // Reached only if the guard is missing.
57 println("\nvoucher balance after:", transfer.VoucherBalanceOf(voucherDenom, owner))
58}
59
60func recvPacket(cur realm, clientID, counterpartyID string, trustedHeight types.Height, receiver address) {
61 payload := transfer.NewFungibleTokenPacketData("uphoton", "100", "atone1user", receiver.String(), "")
62 payloadBz := payload.ProtoMarshal()
63
64 specs := ics23.IavlSpec()
65 // NOTE proof generated by:
66 // go run -C ./cmd/gen-proof . 'prefix2' '07-tendermint-42' 'packet' '{"sequence":1,"source_client":"07-tendermint-42","destination_client":"07-tendermint-1","timeout_timestamp":1234571490,"payloads":[{"source_port":"transfer","destination_port":"transfer","encoding":"application/x-protobuf", "value":"Cgd1cGhvdG9uEgMxMDAaCmF0b25lMXVzZXIiKGcxd3ltdTQ3ZHJocjBrdXEyMDk4bTc5Mmx5dGd0ajJueXg3N3lyc20=","version":"ics20-1"}]}'
67 proof := []ics23.CommitmentProof{
68
69 // iavl proof
70 ics23.CommitmentProof_Exist{
71 Exist: &ics23.ExistenceProof{
72 Key: []byte("\x70\x72\x65\x66\x69\x78\x32\x30\x37\x2d\x74\x65\x6e\x64\x65\x72\x6d\x69\x6e\x74\x2d\x34\x32\x01\x00\x00\x00\x00\x00\x00\x00\x01"),
73 Value: []byte("\x12\x6c\xcc\xff\x00\xd6\xb9\x73\x09\xb3\x8b\x1b\xec\x0f\xe2\xef\xc9\x54\xe5\xac\x1d\x90\x47\x36\xd0\x32\xbc\xc0\xb1\x66\xc4\x8f"),
74 Leaf: &ics23.LeafOp{
75 Hash: specs.LeafSpec.Hash,
76 PrehashKey: specs.LeafSpec.PrehashKey,
77 PrehashValue: specs.LeafSpec.PrehashValue,
78 Length: specs.LeafSpec.Length,
79 Prefix: []byte("\x00\x02\x02"),
80 },
81 Path: []*ics23.InnerOp{
82 {
83 Hash: specs.InnerSpec.Hash,
84 Prefix: []byte("\x02\x04\x02\x20\x35\xf8\xea\x80\x53\x90\xe0\x84\x85\x4f\x39\x9b\x42\xcc\xde\xae\xa3\x3a\x1d\xed\xc1\x15\x63\x8a\xc4\x8d\x06\x00\x63\x7d\xba\x1f\x20"),
85 Suffix: []byte(""),
86 },
87 {
88 Hash: specs.InnerSpec.Hash,
89 Prefix: []byte("\x04\x08\x02\x20"),
90 Suffix: []byte("\x20\x79\x8e\x2c\xaa\x96\xfd\xfb\xa3\x76\xdd\xeb\x47\x99\x99\x54\xd2\xf4\x7e\x65\x16\x22\x64\xb0\x53\x6a\xb5\xdf\xf7\xfc\x0a\x2e\x07"),
91 },
92 {
93 Hash: specs.InnerSpec.Hash,
94 Prefix: []byte("\x06\x0c\x02\x20\x9a\xf3\x7d\xd5\x95\xa0\x19\x08\x03\xb5\xe0\x5a\xae\xf4\x2a\xe3\xfa\xd4\x99\xe4\xfb\xe3\x7f\x7c\xd3\x1c\xad\xff\x22\xa9\xee\x74\x20"),
95 Suffix: []byte(""),
96 },
97 },
98 },
99 },
100
101 // rootmulti proof
102 ics23.CommitmentProof_Exist{
103 Exist: &ics23.ExistenceProof{
104 Key: []byte("\x69\x61\x76\x6c\x53\x74\x6f\x72\x65\x4b\x65\x79"),
105 Value: []byte("\x4f\xa3\xdf\x13\x8a\x86\x32\xc8\x3f\xd8\x84\x92\x00\xe0\xf1\xd8\x8a\x05\x36\x85\x32\x15\x1b\x45\x67\xf6\x86\xec\xf1\xfb\x9f\x45"),
106 Leaf: &ics23.LeafOp{
107 Hash: specs.LeafSpec.Hash,
108 PrehashKey: specs.LeafSpec.PrehashKey,
109 PrehashValue: specs.LeafSpec.PrehashValue,
110 Length: specs.LeafSpec.Length,
111 Prefix: []byte("\x00"),
112 },
113 Path: []*ics23.InnerOp{},
114 },
115 },
116 }
117 recvPacket := types.MsgRecvPacket{
118 Packet: types.Packet{
119 Sequence: 1,
120 SourceClient: counterpartyID,
121 DestinationClient: clientID,
122 TimeoutTimestamp: uint64(time.Now().Add(time.Hour).Unix()),
123 Payloads: []types.Payload{{
124 SourcePort: transfer.PortID,
125 DestinationPort: transfer.PortID,
126 Encoding: transfer.EncodingProtobuf,
127 Value: payloadBz,
128 Version: transfer.V1,
129 }},
130 },
131 ProofCommitment: proof,
132 ProofHeight: trustedHeight,
133 }
134
135 core.RecvPacket(cross(cur), recvPacket)
136}
137
138// Error:
139// voucher transfer must not include native coins