Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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)