z5ab_transfer_voucher_confused_deputy_filetest.gno
5.51 Kb · 134 lines
1// PKGPATH: gno.land/r/aib/main
2package main
3
4// Regression test: an IBC voucher Transfer initiated by a non-user caller
5// (a realm, not a direct maketx call) must be rejected, mirroring the guard
6// the native branch already enforces.
7//
8// Here the immediate caller of transfer.Transfer is the gno.land/r/aib/main
9// realm while the vouchers belong to OriginCaller. No
10// testing.SetRealm(NewUserRealm(...)) is performed, so cur.Previous().IsUserCall()
11// is false inside Transfer.
12
13import (
14 "encoding/hex"
15 "time"
16
17 tmtesting "gno.land/p/aib/ibc/lightclient/tendermint/testing"
18 "gno.land/p/aib/ibc/types"
19
20 "gno.land/p/aib/ics23"
21 "gno.land/r/aib/ibc/apps/transfer"
22 "gno.land/r/aib/ibc/core"
23)
24
25func main(cur realm) {
26 var (
27 chainID = "chain-id-2"
28 trustedHeight = types.NewHeight(2, 2)
29 clientState = tmtesting.NewClientState(chainID, trustedHeight)
30 apphash, _ = hex.DecodeString("0eadf50c7992d8e1366b8ea63ab7d1346de4762c3d449764ef7dc404ba48381f")
31 trustedValset = tmtesting.GenValset()
32 consensusState = tmtesting.GenConsensusState(time.Now(), apphash, trustedValset.Hash())
33 counterpartyID = "07-tendermint-42"
34 )
35 clientID := core.CreateClient(cross(cur), clientState, consensusState)
36 core.RegisterCounterparty(cross(cur), clientID, [][]byte{[]byte("iavlStoreKey"), []byte("prefix2")}, counterpartyID)
37
38 // The voucher owner is the signing EOA (OriginCaller). RecvPacket mints 100
39 // vouchers to it so the balance is non-zero.
40 owner := cur.Previous().Address()
41 recvPacket(cur, clientID, counterpartyID, trustedHeight, owner)
42
43 // ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8
44 voucherDenom := transfer.NewDenom("uphoton", transfer.NewHop(transfer.PortID, clientID)).IBCDenom()
45 println("\nvoucher balance before:", transfer.VoucherBalanceOf(voucherDenom, owner))
46
47 // Transfer is invoked while the immediate caller is a realm, not the user.
48 // The guard must reject it before any voucher is moved.
49 transfer.Transfer(cross(cur), clientID, "atone1user", voucherDenom, 100, uint64(time.Now().Add(time.Hour).Unix()), "memo")
50
51 // Reached only if the guard is missing.
52 println("\nvoucher balance after:", transfer.VoucherBalanceOf(voucherDenom, owner))
53}
54
55func recvPacket(cur realm, clientID, counterpartyID string, trustedHeight types.Height, receiver address) {
56 payload := transfer.NewFungibleTokenPacketData("uphoton", "100", "atone1user", receiver.String(), "")
57 payloadBz := payload.ProtoMarshal()
58
59 specs := ics23.IavlSpec()
60 // NOTE proof generated by:
61 // 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"}]}'
62 proof := []ics23.CommitmentProof{
63
64 // iavl proof
65 ics23.CommitmentProof_Exist{
66 Exist: &ics23.ExistenceProof{
67 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"),
68 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"),
69 Leaf: &ics23.LeafOp{
70 Hash: specs.LeafSpec.Hash,
71 PrehashKey: specs.LeafSpec.PrehashKey,
72 PrehashValue: specs.LeafSpec.PrehashValue,
73 Length: specs.LeafSpec.Length,
74 Prefix: []byte("\x00\x02\x02"),
75 },
76 Path: []*ics23.InnerOp{
77 {
78 Hash: specs.InnerSpec.Hash,
79 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"),
80 Suffix: []byte(""),
81 },
82 {
83 Hash: specs.InnerSpec.Hash,
84 Prefix: []byte("\x04\x08\x02\x20"),
85 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"),
86 },
87 {
88 Hash: specs.InnerSpec.Hash,
89 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"),
90 Suffix: []byte(""),
91 },
92 },
93 },
94 },
95
96 // rootmulti proof
97 ics23.CommitmentProof_Exist{
98 Exist: &ics23.ExistenceProof{
99 Key: []byte("\x69\x61\x76\x6c\x53\x74\x6f\x72\x65\x4b\x65\x79"),
100 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"),
101 Leaf: &ics23.LeafOp{
102 Hash: specs.LeafSpec.Hash,
103 PrehashKey: specs.LeafSpec.PrehashKey,
104 PrehashValue: specs.LeafSpec.PrehashValue,
105 Length: specs.LeafSpec.Length,
106 Prefix: []byte("\x00"),
107 },
108 Path: []*ics23.InnerOp{},
109 },
110 },
111 }
112 recvPacket := types.MsgRecvPacket{
113 Packet: types.Packet{
114 Sequence: 1,
115 SourceClient: counterpartyID,
116 DestinationClient: clientID,
117 TimeoutTimestamp: uint64(time.Now().Add(time.Hour).Unix()),
118 Payloads: []types.Payload{{
119 SourcePort: transfer.PortID,
120 DestinationPort: transfer.PortID,
121 Encoding: transfer.EncodingProtobuf,
122 Value: payloadBz,
123 Version: transfer.V1,
124 }},
125 },
126 ProofCommitment: proof,
127 ProofHeight: trustedHeight,
128 }
129
130 core.RecvPacket(cross(cur), recvPacket)
131}
132
133// Error:
134// voucher transfer must be a direct user call (maketx call)