@agoric/cosmos 0.35.0-u18.4 → 0.35.0-u18a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/ante/inbound_test.go +2 -2
  3. package/app/app.go +26 -9
  4. package/app/upgrade.go +47 -134
  5. package/daemon/cmd/root.go +48 -15
  6. package/git-revision.txt +1 -1
  7. package/go.mod +82 -71
  8. package/go.sum +200 -167
  9. package/package.json +2 -2
  10. package/proto/agoric/swingset/swingset.proto +25 -0
  11. package/proto/agoric/vbank/vbank.proto +7 -0
  12. package/types/address_hooks.go +242 -0
  13. package/types/address_hooks_test.go +221 -0
  14. package/x/swingset/genesis.go +99 -21
  15. package/x/swingset/keeper/keeper.go +16 -7
  16. package/x/swingset/module.go +17 -2
  17. package/x/swingset/testing/queue.go +8 -0
  18. package/x/swingset/types/default-params.go +31 -5
  19. package/x/swingset/types/expected_keepers.go +2 -2
  20. package/x/swingset/types/msgs.go +34 -12
  21. package/x/swingset/types/params.go +53 -43
  22. package/x/swingset/types/params_test.go +75 -9
  23. package/x/swingset/types/swingset.pb.go +386 -56
  24. package/x/vbank/README.md +6 -1
  25. package/x/vbank/keeper/keeper.go +4 -9
  26. package/x/vbank/keeper/migrations.go +30 -0
  27. package/x/vbank/module.go +8 -2
  28. package/x/vbank/types/params.go +43 -2
  29. package/x/vbank/types/vbank.pb.go +105 -36
  30. package/x/vbank/vbank_test.go +12 -7
  31. package/x/vibc/keeper/keeper.go +2 -5
  32. package/x/vibc/keeper/triggers.go +3 -6
  33. package/x/vibc/types/receiver.go +11 -5
  34. package/x/vstorage/testing/queue.go +10 -3
  35. package/x/vtransfer/ibc_middleware.go +5 -1
  36. package/x/vtransfer/ibc_middleware_test.go +511 -145
  37. package/x/vtransfer/keeper/keeper.go +215 -50
  38. package/x/vtransfer/types/genesis.pb.go +1 -0
  39. package/x/vtransfer/utils_test.go +111 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/cosmos",
3
- "version": "0.35.0-u18.4",
3
+ "version": "0.35.0-u18a.0",
4
4
  "description": "Connect JS to the Cosmos blockchain SDK",
5
5
  "parsers": {
6
6
  "js": "mjs"
@@ -39,5 +39,5 @@
39
39
  "typeCoverage": {
40
40
  "atLeast": 0
41
41
  },
42
- "gitHead": "ff46c4aacd7b01ce8ea1fa14b77c187efa9a3b7f"
42
+ "gitHead": "4e4d2b4dedc5a268178712fc6beb89496518480a"
43
43
  }
@@ -82,6 +82,18 @@ message Params {
82
82
  repeated QueueSize queue_max = 5 [
83
83
  (gogoproto.nullable) = false
84
84
  ];
85
+
86
+ // Vat cleanup budget values.
87
+ // These values are used by SwingSet to control the pace of removing data
88
+ // associated with a terminated vat as described at
89
+ // https://github.com/Agoric/agoric-sdk/blob/master/packages/SwingSet/docs/run-policy.md#terminated-vat-cleanup
90
+ //
91
+ // There is no required order to this list of entries, but all the chain
92
+ // nodes must all serialize and deserialize the existing order without
93
+ // permuting it.
94
+ repeated UintMapEntry vat_cleanup_budget = 6 [
95
+ (gogoproto.nullable) = false
96
+ ];
85
97
  }
86
98
 
87
99
  // The current state of the module.
@@ -119,6 +131,7 @@ message PowerFlagFee {
119
131
  }
120
132
 
121
133
  // Map element of a string key to a size.
134
+ // TODO: Replace with UintMapEntry?
122
135
  message QueueSize {
123
136
  option (gogoproto.equal) = true;
124
137
 
@@ -129,6 +142,18 @@ message QueueSize {
129
142
  int32 size = 2;
130
143
  }
131
144
 
145
+ // Map element of a string key to an unsigned integer.
146
+ // The value uses cosmos-sdk Uint rather than a native Go type to ensure that
147
+ // zeroes survive "omitempty" JSON serialization.
148
+ message UintMapEntry {
149
+ option (gogoproto.equal) = true;
150
+ string key = 1;
151
+ string value = 2 [
152
+ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint",
153
+ (gogoproto.nullable) = false
154
+ ];
155
+ }
156
+
132
157
  // Egress is the format for a swingset egress.
133
158
  message Egress {
134
159
  option (gogoproto.equal) = false;
@@ -33,6 +33,13 @@ message Params {
33
33
  int64 reward_smoothing_blocks = 3 [
34
34
  (gogoproto.moretags) = "yaml:\"reward_smoothing_blocks\""
35
35
  ];
36
+
37
+ // allowed_monitoring_accounts is an array of account addresses that can be
38
+ // monitored for sends and receives. An element of `"*"` will permit any
39
+ // address.
40
+ repeated string allowed_monitoring_accounts = 4 [
41
+ (gogoproto.moretags) = "yaml:\"allowed_monitoring_accounts\""
42
+ ];
36
43
  }
37
44
 
38
45
  // The current state of the module.
@@ -0,0 +1,242 @@
1
+ package types
2
+
3
+ import (
4
+ "bytes"
5
+ "fmt"
6
+
7
+ "github.com/cosmos/cosmos-sdk/codec"
8
+ "github.com/cosmos/cosmos-sdk/types/bech32"
9
+
10
+ transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
11
+ clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
12
+ channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
13
+ ibcexported "github.com/cosmos/ibc-go/v6/modules/core/exported"
14
+ )
15
+
16
+ type AddressRole string
17
+ type PacketOrigin string
18
+
19
+ const (
20
+ RoleSender AddressRole = "Sender"
21
+ RoleReceiver AddressRole = "Receiver"
22
+
23
+ PacketSrc PacketOrigin = "src"
24
+ PacketDst PacketOrigin = "dst"
25
+
26
+ AddressHookVersion = 0
27
+ BaseAddressLengthBytes = 2
28
+ )
29
+
30
+ // AddressHookBytePrefix is a magic prefix that identifies a hooked address.
31
+ // Chosen to make bech32 address hooks that look like "agoric10rch..."
32
+ var AddressHookBytePrefix = []byte{0x78, 0xf1, 0x70 /* | AddressHookVersion */}
33
+
34
+ func init() {
35
+ if AddressHookVersion&0x0f != AddressHookVersion {
36
+ panic(fmt.Sprintf("AddressHookVersion must be less than 0x10, got 0x%x", AddressHookVersion))
37
+ }
38
+ }
39
+
40
+ // ExtractBaseAddress extracts the base address from an Address Hook. It
41
+ // returns addr verbatim if it is not an Address Hook.
42
+ func ExtractBaseAddress(addr string) (string, error) {
43
+ baseAddr, _, err := SplitHookedAddress(addr)
44
+ if err != nil {
45
+ return "", err
46
+ }
47
+ return baseAddr, nil
48
+ }
49
+
50
+ // SplitHookedAddress splits a hooked address into its base address and hook data.
51
+ // For the JS implementation, look at @agoric/cosmic-proto/src/address-hooks.js.
52
+ func SplitHookedAddress(addr string) (string, []byte, error) {
53
+ prefix, payload, err := bech32.DecodeAndConvert(addr)
54
+ if err != nil {
55
+ return "", []byte{}, err
56
+ }
57
+
58
+ lastPrefixHighNibble := AddressHookBytePrefix[len(AddressHookBytePrefix)-1]
59
+ bz := bytes.TrimPrefix(payload, AddressHookBytePrefix[:len(AddressHookBytePrefix)-1])
60
+ if len(bz) == len(payload) || len(bz) == 0 || bz[0]&0xf0 != lastPrefixHighNibble {
61
+ // Return an unhooked address.
62
+ return addr, []byte{}, nil
63
+ }
64
+
65
+ version := bz[0] & 0x0f
66
+ bz = bz[1:]
67
+ if version != AddressHookVersion {
68
+ return "", []byte{}, fmt.Errorf("unsupported address hook version %d", version)
69
+ }
70
+
71
+ if len(bz) < BaseAddressLengthBytes {
72
+ return "", []byte{}, fmt.Errorf("hooked address must have at least %d bytes", BaseAddressLengthBytes)
73
+ }
74
+
75
+ b := 0
76
+ for i := BaseAddressLengthBytes - 1; i >= 0; i -= 1 {
77
+ byteVal := bz[len(bz)-1-i]
78
+ b <<= 8
79
+ b |= int(byteVal)
80
+ }
81
+
82
+ payloadEnd := len(bz) - BaseAddressLengthBytes
83
+ if b > payloadEnd {
84
+ return "", []byte{}, fmt.Errorf("base address length 0x%x is longer than payload end 0x%x", b, payloadEnd)
85
+ }
86
+
87
+ baseAddressBuf := bz[0:b]
88
+ baseAddress, err := bech32.ConvertAndEncode(prefix, baseAddressBuf)
89
+ if err != nil {
90
+ return "", []byte{}, err
91
+ }
92
+
93
+ return baseAddress, bz[b:payloadEnd], nil
94
+ }
95
+
96
+ // JoinHookedAddress joins a base bech32 address with hook data to create a
97
+ // hooked bech32 address.
98
+ // For the JS implementation, look at @agoric/cosmic-proto/src/address-hooks.js
99
+ func JoinHookedAddress(baseAddr string, hookData []byte) (string, error) {
100
+ prefix, bz, err := bech32.DecodeAndConvert(baseAddr)
101
+ if err != nil {
102
+ return "", err
103
+ }
104
+
105
+ b := len(bz)
106
+ maxB := 1<<(8*BaseAddressLengthBytes-1) + 1
107
+ if b > maxB {
108
+ return "", fmt.Errorf("base address length 0x%x is longer than the maximum 0x%x", b, maxB)
109
+ }
110
+
111
+ payload := make([]byte, 0, len(AddressHookBytePrefix)+b+len(hookData)+BaseAddressLengthBytes)
112
+ payload = append(payload, AddressHookBytePrefix...)
113
+ payload[len(payload)-1] |= byte(AddressHookVersion)
114
+ payload = append(payload, bz...)
115
+ payload = append(payload, hookData...)
116
+ baLen := make([]byte, BaseAddressLengthBytes)
117
+ for i := BaseAddressLengthBytes - 1; i >= 0; i -= 1 {
118
+ baLen[i] = byte(b)
119
+ b >>= 8
120
+ }
121
+ payload = append(payload, baLen...)
122
+
123
+ return bech32.ConvertAndEncode(prefix, payload)
124
+ }
125
+
126
+ // extractBaseTransferData returns the base address from the transferData.Sender
127
+ // (if RoleSender) or transferData.Receiver (if RoleReceiver). Errors in
128
+ // determining the base address are ignored... we then assume the base address
129
+ // is exactly the original address. If newTransferData is not nil, it will be
130
+ // populated with a new FungibleTokenPacketData consisting of the role replaced
131
+ // with its base address.
132
+ func extractBaseTransferData(transferData transfertypes.FungibleTokenPacketData, role AddressRole, newTransferData *transfertypes.FungibleTokenPacketData) (string, error) {
133
+ var target string
134
+ sender := transferData.Sender
135
+ receiver := transferData.Receiver
136
+
137
+ switch role {
138
+ case RoleSender:
139
+ baseSender, err := ExtractBaseAddress(sender)
140
+ if err == nil {
141
+ sender = baseSender
142
+ }
143
+ target = sender
144
+
145
+ case RoleReceiver:
146
+ baseReceiver, err := ExtractBaseAddress(receiver)
147
+ if err == nil {
148
+ receiver = baseReceiver
149
+ }
150
+ target = receiver
151
+
152
+ default:
153
+ err := fmt.Errorf("invalid address role: %s", role)
154
+ return target, err
155
+ }
156
+
157
+ if newTransferData == nil {
158
+ return target, nil
159
+ }
160
+
161
+ // Create the new transfer data.
162
+ *newTransferData = transfertypes.NewFungibleTokenPacketData(
163
+ transferData.Denom,
164
+ transferData.Amount,
165
+ sender, receiver,
166
+ transferData.Memo,
167
+ )
168
+
169
+ return target, nil
170
+ }
171
+
172
+ // ExtractBaseAddressFromPacket returns the base address from a transfer
173
+ // packet's data, either Sender (if role is RoleSender) or Receiver (if role is
174
+ // RoleReceiver).
175
+ // Errors in determining the base address are ignored... we then assume the base
176
+ // address is exactly the original address.
177
+ // If newPacket is not nil, it is populated with a new transfer packet whose
178
+ // corresponding Sender or Receiver is replaced with the extracted base address.
179
+ func ExtractBaseAddressFromPacket(cdc codec.Codec, packet ibcexported.PacketI, role AddressRole, newPacket *channeltypes.Packet) (string, error) {
180
+ var newDataP *[]byte
181
+ if newPacket != nil {
182
+ // Capture the data for the new packet.
183
+ newDataP = new([]byte)
184
+ }
185
+ target, err := ExtractBaseAddressFromData(cdc, packet.GetData(), role, newDataP)
186
+ if err != nil {
187
+ return target, err
188
+ }
189
+
190
+ if newPacket == nil {
191
+ return target, nil
192
+ }
193
+
194
+ // Create a new packet with the new transfer packet data.
195
+ *newPacket = channeltypes.NewPacket(
196
+ *newDataP, packet.GetSequence(),
197
+ packet.GetSourcePort(), packet.GetSourceChannel(),
198
+ packet.GetDestPort(), packet.GetDestChannel(),
199
+ clienttypes.MustParseHeight(packet.GetTimeoutHeight().String()),
200
+ packet.GetTimeoutTimestamp(),
201
+ )
202
+
203
+ return target, nil
204
+ }
205
+
206
+ // ExtractBaseAddressFromData returns the base address from a transfer packet's data,
207
+ // either Sender (if role is RoleSender) or Receiver (if role is RoleReceiver).
208
+ // Errors in determining the base address are ignored... we then assume the base
209
+ // address is exactly the original address.
210
+ // If newDataP is not nil, it is populated with new transfer packet data whose
211
+ // corresponding Sender or Receiver is replaced with the extracted base address.
212
+ func ExtractBaseAddressFromData(cdc codec.Codec, data []byte, role AddressRole, newDataP *[]byte) (string, error) {
213
+ transferData := transfertypes.FungibleTokenPacketData{}
214
+
215
+ if err := cdc.UnmarshalJSON(data, &transferData); err != nil {
216
+ return "", err
217
+ }
218
+
219
+ var newTransferData *transfertypes.FungibleTokenPacketData
220
+ if newDataP != nil {
221
+ // Capture the transfer data for the new packet data.
222
+ newTransferData = &transfertypes.FungibleTokenPacketData{}
223
+ }
224
+ target, err := extractBaseTransferData(transferData, role, newTransferData)
225
+ if err != nil {
226
+ return target, err
227
+ }
228
+
229
+ if newDataP == nil {
230
+ return target, nil
231
+ }
232
+
233
+ // Reuse the original data if we didn't transform it.
234
+ if transferData == *newTransferData {
235
+ *newDataP = bytes.Clone(data)
236
+ } else {
237
+ // Re-serialize the packet data with the new base address.
238
+ *newDataP = newTransferData.GetBytes()
239
+ }
240
+
241
+ return target, nil
242
+ }
@@ -0,0 +1,221 @@
1
+ package types_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/require"
7
+
8
+ codec "github.com/cosmos/cosmos-sdk/codec"
9
+ cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
10
+
11
+ transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
12
+ clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
13
+ channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
14
+
15
+ "github.com/Agoric/agoric-sdk/golang/cosmos/types"
16
+ )
17
+
18
+ func TestSplitHookedAddress(t *testing.T) {
19
+ cases := []struct {
20
+ name string
21
+ hook string
22
+ baseAddr string
23
+ hookData []byte
24
+ err string
25
+ }{
26
+ {"empty", "", "", []byte{}, "decoding bech32 failed: invalid bech32 string length 0"},
27
+ {"no hook", "agoric1qqp0e5ys", "agoric1qqp0e5ys", []byte{}, ""},
28
+ {"Fast USDC", "agoric10rchp4vc53apxn32q42c3zryml8xq3xshyzuhjk6405wtxy7tl3d7e0f8az423padaek6me38qekget2vdhx66mtvy6kg7nrw5uhsaekd4uhwufswqex6dtsv44hxv3cd4jkuqpqvduyhf",
29
+ "agoric16kv2g7snfc4q24vg3pjdlnnqgngtjpwtetd2h689nz09lcklvh5s8u37ek",
30
+ []byte("?EUD=osmo183dejcnmkka5dzcu9xw6mywq0p2m5peks28men"),
31
+ ""},
32
+ {"version 0",
33
+ "agoric10rchqqqpqgpsgpgxquyqjzstpsxsurcszyfpxpqrqgqsq9qx0p9wp",
34
+ "agoric1qqqsyqcyq5rqwzqfpg9scrgwpugpzysn3tn9p0",
35
+ []byte{4, 3, 2, 1},
36
+ ""},
37
+ {"version 1 reject",
38
+ "agoric10rchzqqpqgpsgpgxquyqjzstpsxsurcszyfpxpqrqgqsq9q04n2fg",
39
+ "",
40
+ []byte{},
41
+ "unsupported address hook version 1"},
42
+ {"version 15 reject",
43
+ "agoric10rch7qqpqgpsgpgxquyqjzstpsxsurcszyfpxpqrqgqsq9q25ez2d",
44
+ "",
45
+ []byte{},
46
+ "unsupported address hook version 15"},
47
+ }
48
+
49
+ for _, tc := range cases {
50
+ tc := tc
51
+ t.Run(tc.name, func(t *testing.T) {
52
+ baseAddr, hookData, err := types.SplitHookedAddress(tc.hook)
53
+ if len(tc.err) > 0 {
54
+ require.Error(t, err)
55
+ require.Equal(t, tc.err, err.Error())
56
+ } else {
57
+ require.NoError(t, err)
58
+ require.Equal(t, tc.baseAddr, baseAddr)
59
+ require.Equal(t, string(tc.hookData), string(hookData))
60
+ }
61
+ })
62
+ }
63
+ }
64
+
65
+ func TestExtractBaseAddress(t *testing.T) {
66
+ bases := []struct {
67
+ name string
68
+ addr string
69
+ }{
70
+ {"agoric address", "agoric1qqp0e5ys"},
71
+ {"cosmos address", "cosmos1qqxuevtt"},
72
+ }
73
+
74
+ suffixes := []struct {
75
+ hookStr string
76
+ baseIsWrong bool
77
+ isErr bool
78
+ }{
79
+ {"", false, false},
80
+ {"/", false, false},
81
+ {"/sub/account", false, false},
82
+ {"?query=something&k=v&k2=v2", false, false},
83
+ {"?query=something&k=v&k2=v2#fragment", false, false},
84
+ {"unexpected", false, false},
85
+ {"\x01", false, false},
86
+ }
87
+
88
+ for _, b := range bases {
89
+ b := b
90
+ for _, s := range suffixes {
91
+ s := s
92
+ t.Run(b.name+" "+s.hookStr, func(t *testing.T) {
93
+ addrHook, err := types.JoinHookedAddress(b.addr, []byte(s.hookStr))
94
+ require.NoError(t, err)
95
+ addr, err := types.ExtractBaseAddress(addrHook)
96
+ if s.isErr {
97
+ require.Error(t, err)
98
+ } else {
99
+ require.NoError(t, err)
100
+ if s.baseIsWrong {
101
+ require.NotEqual(t, b.addr, addr)
102
+ } else {
103
+ require.Equal(t, b.addr, addr)
104
+ addr, hookData, err := types.SplitHookedAddress(addrHook)
105
+ require.NoError(t, err)
106
+ require.Equal(t, b.addr, addr)
107
+ require.Equal(t, s.hookStr, string(hookData))
108
+ }
109
+ }
110
+ })
111
+ }
112
+ }
113
+ }
114
+
115
+ func TestExtractBaseAddressFromPacket(t *testing.T) {
116
+ ir := cdctypes.NewInterfaceRegistry()
117
+ cdc := codec.NewProtoCodec(ir)
118
+ transfertypes.RegisterInterfaces(ir)
119
+ channeltypes.RegisterInterfaces(ir)
120
+ clienttypes.RegisterInterfaces(ir)
121
+
122
+ cosmosAddr := "cosmos1qqxuevtt"
123
+ cosmosHookStr := "?foo=bar&baz=bot#fragment"
124
+ cosmosHook, err := types.JoinHookedAddress(cosmosAddr, []byte(cosmosHookStr))
125
+ require.NoError(t, err)
126
+ addr, hookData, err := types.SplitHookedAddress(cosmosHook)
127
+ require.NoError(t, err)
128
+ require.Equal(t, cosmosAddr, addr)
129
+ require.Equal(t, cosmosHookStr, string(hookData))
130
+
131
+ agoricAddr := "agoric1qqp0e5ys"
132
+ agoricHookStr := "?bingo=again"
133
+ agoricHook, err := types.JoinHookedAddress(agoricAddr, []byte(agoricHookStr))
134
+ require.NoError(t, err)
135
+ addr, hookData, err = types.SplitHookedAddress(agoricHook)
136
+ require.NoError(t, err)
137
+ require.Equal(t, agoricAddr, addr)
138
+ require.Equal(t, agoricHookStr, string(hookData))
139
+
140
+ cases := []struct {
141
+ name string
142
+ addrs map[types.AddressRole]struct{ addr, baseAddr string }
143
+ }{
144
+ {"sender has params",
145
+ map[types.AddressRole]struct{ addr, baseAddr string }{
146
+ types.RoleSender: {cosmosHook, "cosmos1qqxuevtt"},
147
+ types.RoleReceiver: {"agoric1qqp0e5ys", "agoric1qqp0e5ys"},
148
+ },
149
+ },
150
+ {"receiver has params",
151
+ map[types.AddressRole]struct{ addr, baseAddr string }{
152
+ types.RoleSender: {"cosmos1qqxuevtt", "cosmos1qqxuevtt"},
153
+ types.RoleReceiver: {agoricHook, "agoric1qqp0e5ys"},
154
+ },
155
+ },
156
+ {"both are base",
157
+ map[types.AddressRole]struct{ addr, baseAddr string }{
158
+ types.RoleSender: {"cosmos1qqxuevtt", "cosmos1qqxuevtt"},
159
+ types.RoleReceiver: {"agoric1qqp0e5ys", "agoric1qqp0e5ys"},
160
+ },
161
+ },
162
+ {"both have params",
163
+ map[types.AddressRole]struct{ addr, baseAddr string }{
164
+ types.RoleSender: {agoricHook, "agoric1qqp0e5ys"},
165
+ types.RoleReceiver: {cosmosHook, "cosmos1qqxuevtt"},
166
+ },
167
+ },
168
+ }
169
+
170
+ for _, tc := range cases {
171
+ tc := tc
172
+ t.Run(tc.name, func(t *testing.T) {
173
+ ftPacketData := transfertypes.NewFungibleTokenPacketData("denom", "100", tc.addrs[types.RoleSender].addr, tc.addrs[types.RoleReceiver].addr, "my-favourite-memo")
174
+ packetBz := ftPacketData.GetBytes()
175
+ packet := channeltypes.NewPacket(packetBz, 1234, "my-port", "my-channel", "their-port", "their-channel", clienttypes.NewHeight(133, 445), 10999)
176
+
177
+ for role, addrs := range tc.addrs {
178
+ addrs := addrs
179
+ role := role
180
+
181
+ t.Run(string(role), func(t *testing.T) {
182
+ baseAddr, err := types.ExtractBaseAddress(addrs.addr)
183
+ require.NoError(t, err)
184
+ require.Equal(t, addrs.baseAddr, baseAddr)
185
+
186
+ packetBaseAddr0, err := types.ExtractBaseAddressFromData(cdc, packet.GetData(), role, nil)
187
+ require.NoError(t, err)
188
+ require.Equal(t, addrs.baseAddr, packetBaseAddr0)
189
+
190
+ packetBaseAddr1, err := types.ExtractBaseAddressFromPacket(cdc, packet, role, nil)
191
+ require.NoError(t, err)
192
+ require.Equal(t, addrs.baseAddr, packetBaseAddr1)
193
+
194
+ var newPacket channeltypes.Packet
195
+ packetBaseAddr2, err := types.ExtractBaseAddressFromPacket(cdc, packet, role, &newPacket)
196
+ require.NoError(t, err)
197
+ require.Equal(t, addrs.baseAddr, packetBaseAddr2)
198
+
199
+ var basePacketData transfertypes.FungibleTokenPacketData
200
+ err = cdc.UnmarshalJSON(newPacket.GetData(), &basePacketData)
201
+ require.NoError(t, err)
202
+
203
+ // Check that the only difference between the packet data is the baseAddr.
204
+ packetData := basePacketData
205
+ switch role {
206
+ case types.RoleSender:
207
+ require.Equal(t, addrs.baseAddr, basePacketData.Sender)
208
+ packetData.Sender = addrs.addr
209
+ case types.RoleReceiver:
210
+ require.Equal(t, addrs.baseAddr, basePacketData.Receiver)
211
+ packetData.Receiver = addrs.addr
212
+ default:
213
+ t.Fatal("unexpected role", role)
214
+ }
215
+
216
+ require.Equal(t, ftPacketData, packetData)
217
+ })
218
+ }
219
+ })
220
+ }
221
+ }