@wormhole-foundation/wormhole-solidity-sdk 1.0.1

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 (56) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +78 -0
  3. package/contracts/Executor/Integration.sol +180 -0
  4. package/contracts/Executor/RelayInstruction.sol +108 -0
  5. package/contracts/Executor/Request.sol +43 -0
  6. package/contracts/RawDispatcher.sol +29 -0
  7. package/contracts/Utils.sol +27 -0
  8. package/contracts/WormholeRelayer/AdditionalMessages.sol +37 -0
  9. package/contracts/WormholeRelayer/Keys.sol +198 -0
  10. package/contracts/WormholeRelayer/Receiver.sol +44 -0
  11. package/contracts/WormholeRelayer/Sender.sol +264 -0
  12. package/contracts/WormholeRelayer.sol +7 -0
  13. package/contracts/constants/CctpDomainMapping.sol +72 -0
  14. package/contracts/constants/CctpDomains.sol +21 -0
  15. package/contracts/constants/Chains.sol +66 -0
  16. package/contracts/constants/Common.sol +17 -0
  17. package/contracts/constants/ConsistencyLevel.sol +9 -0
  18. package/contracts/interfaces/ICoreBridge.sol +80 -0
  19. package/contracts/interfaces/ICustomConsistencyLevel.sol +12 -0
  20. package/contracts/interfaces/IDeliveryProvider.sol +84 -0
  21. package/contracts/interfaces/IExecutor.sol +32 -0
  22. package/contracts/interfaces/ITokenBridge.sol +81 -0
  23. package/contracts/interfaces/IWormholeRelayer.sol +658 -0
  24. package/contracts/interfaces/cctp/IMessageTransmitter.sol +76 -0
  25. package/contracts/interfaces/cctp/ITokenMessenger.sol +72 -0
  26. package/contracts/interfaces/cctp/ITokenMinter.sol +40 -0
  27. package/contracts/interfaces/cctp/shared/IOwnable2Step.sol +18 -0
  28. package/contracts/interfaces/cctp/shared/IPausable.sol +20 -0
  29. package/contracts/interfaces/token/IERC20.sol +16 -0
  30. package/contracts/interfaces/token/IERC20Metadata.sol +11 -0
  31. package/contracts/interfaces/token/IERC20Permit.sol +19 -0
  32. package/contracts/interfaces/token/IWETH.sol +12 -0
  33. package/contracts/libraries/BytesParsing.sol +2848 -0
  34. package/contracts/libraries/CctpMessages.sol +755 -0
  35. package/contracts/libraries/CoreBridge.sol +365 -0
  36. package/contracts/libraries/CustomConsistency.sol +60 -0
  37. package/contracts/libraries/Percentage.sol +99 -0
  38. package/contracts/libraries/PermitParsing.sol +580 -0
  39. package/contracts/libraries/QueryResponse.sol +741 -0
  40. package/contracts/libraries/ReplayProtection.sol +106 -0
  41. package/contracts/libraries/SafeERC20.sol +67 -0
  42. package/contracts/libraries/TokenBridgeMessages.sol +742 -0
  43. package/contracts/libraries/TypedUnits.sol +304 -0
  44. package/contracts/libraries/UncheckedIndexing.sol +99 -0
  45. package/contracts/libraries/VaaLib.sol +1385 -0
  46. package/contracts/proxy/Eip1967Admin.sol +20 -0
  47. package/contracts/proxy/Eip1967Implementation.sol +15 -0
  48. package/contracts/proxy/Proxy.sol +43 -0
  49. package/contracts/proxy/ProxyBase.sol +80 -0
  50. package/contracts/utils/DecimalNormalization.sol +18 -0
  51. package/contracts/utils/EagerOps.sol +18 -0
  52. package/contracts/utils/Keccak.sol +39 -0
  53. package/contracts/utils/Revert.sol +11 -0
  54. package/contracts/utils/Transfer.sol +23 -0
  55. package/contracts/utils/UniversalAddress.sol +17 -0
  56. package/package.json +23 -0
@@ -0,0 +1,742 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.14; //for (bugfixed) support of `using ... global;` syntax for libraries
3
+
4
+ import {WORD_SIZE} from "../constants/Common.sol";
5
+ import {BytesParsing} from "./BytesParsing.sol";
6
+
7
+ // ╭─────────────────────────────────────────────────────────────╮
8
+ // │ Library for encoding and decoding Wormhole TokenBridge VAAs │
9
+ // ╰─────────────────────────────────────────────────────────────╯
10
+
11
+ // # Payload Formats
12
+ //
13
+ // see:
14
+ // * [TokenBridge](https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/bridge/Bridge.sol#L595-L629)
15
+ // * [Typescript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/definitions/src/protocols/tokenBridge/tokenBridgeLayout.ts)
16
+ //
17
+ // ╭────────────┬──────────────────┬────────────────────────────────────────────────────────╮
18
+ // │ Type │ Name │ Description │
19
+ // ┝━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
20
+ // │ CommonTransferHeader (shared by Transfer and TransferWithPayload) │
21
+ // ├────────────┬──────────────────┬────────────────────────────────────────────────────────┤
22
+ // │ uint8 │ payloadId │ either 1 or 3 (see PAYLOAD_ID constants below) │
23
+ // │ uint256 │ normalizedAmount │ amount of transferred tokens truncated to 8 decimals │
24
+ // │ bytes32 │ tokenAddress │ address of the token on the origin chain │
25
+ // │ uint16 │ tokenChainId │ Wormhole chain id of the token's origin chain │
26
+ // │ bytes32 │ toAddress │ address of the recipient on the destination chain │
27
+ // │ uint16 │ toChainId │ Wormhole chain id of the destination chain │
28
+ // ┝━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
29
+ // │ Transfer │
30
+ // ├────────────────────────────────────────────────────────────────────────────────────────┤
31
+ // │ CommonTransferHeader │
32
+ // ├╌╌╌╌╌╌╌╌╌╌╌╌┬╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┬╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
33
+ // │ uint256 │ fee │ ignored/unused legacy field, should always be 0 │
34
+ // ┝━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
35
+ // │ TransferWithPayload │
36
+ // ├────────────────────────────────────────────────────────────────────────────────────────┤
37
+ // │ CommonTransferHeader │
38
+ // ├╌╌╌╌╌╌╌╌╌╌╌╌┬╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┬╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
39
+ // │ bytes32 │ fromAddress │ address of the sender on the origin chain │
40
+ // │ bytes │ payload │ additional payload of the transfer │
41
+ // ┝━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
42
+ // │ AttestMeta │
43
+ // ├────────────┬──────────────────┬────────────────────────────────────────────────────────┤
44
+ // │ uint8 │ payloadId │ fixed value: 2 (see PAYLOAD_ID_ATTEST_META below) │
45
+ // │ bytes32 │ tokenAddress │ address of the token on the origin chain │
46
+ // │ uint16 │ tokenChainId │ Wormhole chain id of the origin chain │
47
+ // │ uint8 │ decimals │ number of decimals of the token │
48
+ // │ bytes32 │ symbol │ symbol of the token │
49
+ // │ bytes32 │ name │ name of the token │
50
+ // ╰────────────┴──────────────────┴────────────────────────────────────────────────────────╯
51
+ //
52
+ // # Library Functions & Naming Conventions
53
+ //
54
+ // All decode library functions come in 2x2=4 flavors:
55
+ // 1. Data-Location:
56
+ // 1.1. Calldata (using the Cd tag)
57
+ // 1.2. Memory (using the Mem tag)
58
+ // 2. Return Value:
59
+ // 2.1. individual, stack-based return values (no extra tag)
60
+ // 2.2. the associated, memory-allocated Struct (using the Struct tag)
61
+ //
62
+ // Additionally, like in BytesParsing, the Unchecked function name suffix does not refer to
63
+ // Solidity's `unchecked` keyword, but rather to the fact that no bounds checking is performed.
64
+ //
65
+ // Decoding functions flavorless base names:
66
+ // * decodeTransfer
67
+ // * decodeTransferWithPayload
68
+ // * decodeAttestMeta
69
+ //
70
+ // Encoding functions (should only be relevant for testing):
71
+ // * encode (overloaded for each struct)
72
+ // * encodeTransfer
73
+ // * encodeTransferWithPayload
74
+ // * encodeAttestMeta
75
+ //
76
+ // Other functions:
77
+ // * checkPayloadId
78
+
79
+ struct TokenBridgeTransfer {
80
+ //uint8 payloadId; //see PAYLOAD_ID_TRANSFER
81
+ uint256 normalizedAmount;
82
+ bytes32 tokenAddress;
83
+ uint16 tokenChainId;
84
+ bytes32 toAddress;
85
+ uint16 toChainId;
86
+ //uint256 fee; //discarded
87
+ }
88
+
89
+ struct TokenBridgeTransferWithPayload {
90
+ //uint8 payloadId; //see PAYLOAD_ID_TRANSFER_WITH_PAYLOAD
91
+ uint256 normalizedAmount;
92
+ bytes32 tokenAddress;
93
+ uint16 tokenChainId;
94
+ bytes32 toAddress;
95
+ uint16 toChainId;
96
+ bytes32 fromAddress;
97
+ bytes payload;
98
+ }
99
+
100
+ struct TokenBridgeTransferWithPayloadEssentials {
101
+ //uint8 payloadId; //see PAYLOAD_ID_TRANSFER_WITH_PAYLOAD
102
+ uint256 normalizedAmount;
103
+ bytes32 tokenAddress;
104
+ uint16 tokenChainId;
105
+ bytes32 fromAddress;
106
+ bytes payload;
107
+ }
108
+
109
+ struct TokenBridgeAttestMeta {
110
+ //uint8 payloadId; //see PAYLOAD_ID_ATTEST_META
111
+ bytes32 tokenAddress;
112
+ uint16 tokenChainId;
113
+ uint8 decimals;
114
+ bytes32 symbol;
115
+ bytes32 name;
116
+ }
117
+
118
+ library TokenBridgeMessageLib {
119
+ using BytesParsing for bytes;
120
+ using {BytesParsing.checkBound, BytesParsing.checkLength} for uint;
121
+
122
+ error InvalidPayloadId(uint8 encoded);
123
+
124
+ //constants are provided to allow more eclectic, manual decoding
125
+ uint8 internal constant PAYLOAD_ID_TRANSFER = 1;
126
+ uint8 internal constant PAYLOAD_ID_TRANSFER_WITH_PAYLOAD = 3;
127
+ uint8 internal constant PAYLOAD_ID_ATTEST_META = 2;
128
+
129
+ uint internal constant PAYLOAD_ID_OFFSET = 0;
130
+ uint internal constant PAYLOAD_ID_SIZE = 1;
131
+
132
+ // Common Transfer format offsets and sizes
133
+ uint internal constant COMMON_TRANSFER_AMOUNT_OFFSET =
134
+ PAYLOAD_ID_OFFSET + PAYLOAD_ID_SIZE;
135
+ uint internal constant COMMON_TRANSFER_AMOUNT_SIZE = 32;
136
+
137
+ uint internal constant COMMON_TRANSFER_TOKEN_ADDRESS_OFFSET =
138
+ COMMON_TRANSFER_AMOUNT_OFFSET + COMMON_TRANSFER_AMOUNT_SIZE;
139
+ uint internal constant COMMON_TRANSFER_TOKEN_ADDRESS_SIZE = 32;
140
+
141
+ uint internal constant COMMON_TRANSFER_TOKEN_CHAIN_ID_OFFSET =
142
+ COMMON_TRANSFER_TOKEN_ADDRESS_OFFSET + COMMON_TRANSFER_TOKEN_ADDRESS_SIZE;
143
+ uint internal constant COMMON_TRANSFER_TOKEN_CHAIN_ID_SIZE = 2;
144
+
145
+ uint internal constant COMMON_TRANSFER_TO_ADDRESS_OFFSET =
146
+ COMMON_TRANSFER_TOKEN_CHAIN_ID_OFFSET + COMMON_TRANSFER_TOKEN_CHAIN_ID_SIZE;
147
+ uint internal constant COMMON_TRANSFER_TO_ADDRESS_SIZE = 32;
148
+
149
+ uint internal constant COMMON_TRANSFER_TO_CHAIN_ID_OFFSET =
150
+ COMMON_TRANSFER_TO_ADDRESS_OFFSET + COMMON_TRANSFER_TO_ADDRESS_SIZE;
151
+ uint internal constant COMMON_TRANSFER_TO_CHAIN_ID_SIZE = 2;
152
+
153
+ uint internal constant COMMON_TRANSFER_SIZE =
154
+ COMMON_TRANSFER_TO_CHAIN_ID_OFFSET + COMMON_TRANSFER_TO_CHAIN_ID_SIZE;
155
+
156
+ // Additional Transfer fields
157
+ uint internal constant TRANSFER_FEE_OFFSET = COMMON_TRANSFER_SIZE;
158
+ uint internal constant TRANSFER_FEE_SIZE = 32;
159
+ uint internal constant TRANSFER_SIZE =
160
+ TRANSFER_FEE_OFFSET + TRANSFER_FEE_SIZE;
161
+
162
+ // Additional TransferWithPayload fields
163
+ uint internal constant TRANSFER_WITH_PAYLOAD_FROM_ADDRESS_OFFSET = COMMON_TRANSFER_SIZE;
164
+ uint internal constant TRANSFER_WITH_PAYLOAD_FROM_ADDRESS_SIZE = 32;
165
+
166
+ uint internal constant TRANSFER_WITH_PAYLOAD_PAYLOAD_OFFSET = //only a mother can love this name
167
+ TRANSFER_WITH_PAYLOAD_FROM_ADDRESS_OFFSET + TRANSFER_WITH_PAYLOAD_FROM_ADDRESS_SIZE;
168
+
169
+ // AttestMeta format offsets and sizes
170
+ uint internal constant ATTEST_META_TOKEN_ADDRESS_OFFSET =
171
+ PAYLOAD_ID_OFFSET + PAYLOAD_ID_SIZE;
172
+ uint internal constant ATTEST_META_TOKEN_ADDRESS_SIZE = 32;
173
+
174
+ uint internal constant ATTEST_META_TOKEN_CHAIN_ID_OFFSET =
175
+ ATTEST_META_TOKEN_ADDRESS_OFFSET + ATTEST_META_TOKEN_ADDRESS_SIZE;
176
+ uint internal constant ATTEST_META_TOKEN_CHAIN_ID_SIZE = 2;
177
+
178
+ uint internal constant ATTEST_META_DECIMALS_OFFSET =
179
+ ATTEST_META_TOKEN_CHAIN_ID_OFFSET + ATTEST_META_TOKEN_CHAIN_ID_SIZE;
180
+ uint internal constant ATTEST_META_DECIMALS_SIZE = 1;
181
+
182
+ uint internal constant ATTEST_META_SYMBOL_OFFSET =
183
+ ATTEST_META_DECIMALS_OFFSET + ATTEST_META_DECIMALS_SIZE;
184
+ uint internal constant ATTEST_META_SYMBOL_SIZE = 32;
185
+
186
+ uint internal constant ATTEST_META_NAME_OFFSET =
187
+ ATTEST_META_SYMBOL_OFFSET + ATTEST_META_SYMBOL_SIZE;
188
+ uint internal constant ATTEST_META_NAME_SIZE = 32;
189
+
190
+ uint internal constant ATTEST_META_SIZE =
191
+ ATTEST_META_NAME_OFFSET + ATTEST_META_NAME_SIZE;
192
+
193
+ // ------------ Decoding ------------
194
+
195
+ function checkPayloadId(uint8 encoded, uint8 expected) internal pure {
196
+ if (encoded != expected)
197
+ revert InvalidPayloadId(encoded);
198
+ }
199
+
200
+ // Transfer
201
+
202
+ function decodeTransferCd(
203
+ bytes calldata encoded
204
+ ) internal pure returns (
205
+ uint256 normalizedAmount,
206
+ bytes32 tokenAddress,
207
+ uint16 tokenChainId,
208
+ bytes32 toAddress,
209
+ uint16 toChainId
210
+ ) {
211
+ uint offset = 0;
212
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, offset) =
213
+ _decodeTransferCommonHeaderCdUnchecked(encoded, PAYLOAD_ID_TRANSFER);
214
+
215
+ offset += WORD_SIZE;
216
+ encoded.length.checkLength(offset);
217
+ }
218
+
219
+ function decodeTransferStructCd(
220
+ bytes calldata encoded
221
+ ) internal pure returns (TokenBridgeTransfer memory transfer) {
222
+ ( transfer.normalizedAmount,
223
+ transfer.tokenAddress,
224
+ transfer.tokenChainId,
225
+ transfer.toAddress,
226
+ transfer.toChainId
227
+ ) = decodeTransferCd(encoded);
228
+ }
229
+
230
+ function decodeTransferMem(
231
+ bytes memory encoded
232
+ ) internal pure returns (
233
+ uint256 normalizedAmount,
234
+ bytes32 tokenAddress,
235
+ uint16 tokenChainId,
236
+ bytes32 toAddress,
237
+ uint16 toChainId
238
+ ) {
239
+ uint offset = 0;
240
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, offset) =
241
+ decodeTransferMemUnchecked(encoded, offset);
242
+ encoded.length.checkLength(offset);
243
+ }
244
+
245
+ function decodeTransferStructMem(
246
+ bytes memory encoded
247
+ ) internal pure returns (TokenBridgeTransfer memory transfer) {
248
+ ( transfer.normalizedAmount,
249
+ transfer.tokenAddress,
250
+ transfer.tokenChainId,
251
+ transfer.toAddress,
252
+ transfer.toChainId
253
+ ) = decodeTransferMem(encoded);
254
+ }
255
+
256
+ function decodeTransferMemUnchecked(
257
+ bytes memory encoded,
258
+ uint offset
259
+ ) internal pure returns (
260
+ uint256 normalizedAmount,
261
+ bytes32 tokenAddress,
262
+ uint16 tokenChainId,
263
+ bytes32 toAddress,
264
+ uint16 toChainId,
265
+ uint newOffset
266
+ ) {
267
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, offset) =
268
+ _decodeTransferCommonHeaderMemUnchecked(encoded, offset, PAYLOAD_ID_TRANSFER);
269
+
270
+ offset += WORD_SIZE;
271
+ newOffset = offset;
272
+ }
273
+
274
+ function decodeTransferStructMemUnchecked(
275
+ bytes memory encoded,
276
+ uint offset
277
+ ) internal pure returns (TokenBridgeTransfer memory transfer, uint newOffset) {
278
+ ( transfer.normalizedAmount,
279
+ transfer.tokenAddress,
280
+ transfer.tokenChainId,
281
+ transfer.toAddress,
282
+ transfer.toChainId,
283
+ newOffset
284
+ ) = decodeTransferMemUnchecked(encoded, offset);
285
+ }
286
+
287
+ // TransferWithPayload
288
+
289
+ function decodeTransferWithPayloadCd(
290
+ bytes calldata encoded
291
+ ) internal pure returns (
292
+ uint256 normalizedAmount,
293
+ bytes32 tokenAddress,
294
+ uint16 tokenChainId,
295
+ bytes32 toAddress,
296
+ uint16 toChainId,
297
+ bytes32 fromAddress,
298
+ bytes calldata payload
299
+ ) { unchecked {
300
+ uint offset = 0;
301
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, offset) =
302
+ _decodeTransferCommonHeaderCdUnchecked(encoded, PAYLOAD_ID_TRANSFER_WITH_PAYLOAD);
303
+
304
+ (fromAddress, offset) = encoded.asBytes32CdUnchecked(offset);
305
+
306
+ offset.checkBound(encoded.length); //check for underflow
307
+ (payload, ) = encoded.sliceCdUnchecked(offset, encoded.length - offset);
308
+ }}
309
+
310
+ function decodeTransferWithPayloadStructCd(
311
+ bytes calldata encoded
312
+ ) internal pure returns (TokenBridgeTransferWithPayload memory twp) {
313
+ ( twp.normalizedAmount,
314
+ twp.tokenAddress,
315
+ twp.tokenChainId,
316
+ twp.toAddress,
317
+ twp.toChainId,
318
+ twp.fromAddress,
319
+ twp.payload
320
+ ) = decodeTransferWithPayloadCd(encoded);
321
+ }
322
+
323
+ function decodeTransferWithPayloadMem(
324
+ bytes memory encoded
325
+ ) internal pure returns (
326
+ uint256 normalizedAmount,
327
+ bytes32 tokenAddress,
328
+ uint16 tokenChainId,
329
+ bytes32 toAddress,
330
+ uint16 toChainId,
331
+ bytes32 fromAddress,
332
+ bytes memory payload
333
+ ) {
334
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, fromAddress, payload, ) =
335
+ decodeTransferWithPayloadMem(encoded, 0, encoded.length);
336
+ }
337
+
338
+ function decodeTransferWithPayloadStructMem(
339
+ bytes memory encoded
340
+ ) internal pure returns (TokenBridgeTransferWithPayload memory twp) {
341
+ (twp, ) = decodeTransferWithPayloadStructMem(encoded, 0, encoded.length);
342
+ }
343
+
344
+ function decodeTransferWithPayloadMem(
345
+ bytes memory encoded,
346
+ uint offset,
347
+ uint length
348
+ ) internal pure returns (
349
+ uint256 normalizedAmount,
350
+ bytes32 tokenAddress,
351
+ uint16 tokenChainId,
352
+ bytes32 toAddress,
353
+ uint16 toChainId,
354
+ bytes32 fromAddress,
355
+ bytes memory payload,
356
+ uint newOffset
357
+ ) { unchecked {
358
+ (normalizedAmount, tokenAddress, tokenChainId, toAddress, toChainId, offset) =
359
+ _decodeTransferCommonHeaderMemUnchecked(encoded, offset, PAYLOAD_ID_TRANSFER_WITH_PAYLOAD);
360
+
361
+ (fromAddress, offset) = encoded.asBytes32MemUnchecked(offset);
362
+
363
+ offset.checkBound(length); //check for underflow
364
+ (payload, newOffset) = encoded.sliceMemUnchecked(offset, length - offset);
365
+
366
+ }}
367
+
368
+ function decodeTransferWithPayloadStructMem(
369
+ bytes memory encoded,
370
+ uint offset,
371
+ uint length
372
+ ) internal pure returns (TokenBridgeTransferWithPayload memory twp, uint newOffset) {
373
+ ( twp.normalizedAmount,
374
+ twp.tokenAddress,
375
+ twp.tokenChainId,
376
+ twp.toAddress,
377
+ twp.toChainId,
378
+ twp.fromAddress,
379
+ twp.payload,
380
+ newOffset
381
+ ) = decodeTransferWithPayloadMem(encoded, offset, length);
382
+ }
383
+
384
+ // TransferWithPayloadEssentials
385
+
386
+ function decodeTransferWithPayloadEssentialsCd(
387
+ bytes calldata encoded
388
+ ) internal pure returns (
389
+ uint256 normalizedAmount,
390
+ bytes32 tokenAddress,
391
+ uint16 tokenChainId,
392
+ bytes32 fromAddress,
393
+ bytes calldata payload
394
+ ) { unchecked {
395
+ uint offset = 0;
396
+ (normalizedAmount, tokenAddress, tokenChainId, offset) =
397
+ _decodeTransferCommonHeaderEssentialsCdUnchecked(encoded, PAYLOAD_ID_TRANSFER_WITH_PAYLOAD);
398
+
399
+ offset += COMMON_TRANSFER_TO_ADDRESS_SIZE + COMMON_TRANSFER_TO_CHAIN_ID_SIZE;
400
+ (fromAddress, offset) = encoded.asBytes32CdUnchecked(offset);
401
+
402
+ offset.checkBound(encoded.length); //check for underflow
403
+ (payload, ) = encoded.sliceCdUnchecked(offset, encoded.length - offset);
404
+ }}
405
+
406
+ function decodeTransferWithPayloadEssentialsStructCd(
407
+ bytes calldata encoded
408
+ ) internal pure returns (TokenBridgeTransferWithPayloadEssentials memory twp) {
409
+ ( twp.normalizedAmount,
410
+ twp.tokenAddress,
411
+ twp.tokenChainId,
412
+ twp.fromAddress,
413
+ twp.payload
414
+ ) = decodeTransferWithPayloadEssentialsCd(encoded);
415
+ }
416
+
417
+ function decodeTransferWithPayloadEssentialsMem(
418
+ bytes memory encoded
419
+ ) internal pure returns (
420
+ uint256 normalizedAmount,
421
+ bytes32 tokenAddress,
422
+ uint16 tokenChainId,
423
+ bytes32 fromAddress,
424
+ bytes memory payload
425
+ ) {
426
+ (normalizedAmount, tokenAddress, tokenChainId, fromAddress, payload, ) =
427
+ decodeTransferWithPayloadEssentialsMem(encoded, 0, encoded.length);
428
+ }
429
+
430
+ function decodeTransferWithPayloadEssentialsStructMem(
431
+ bytes memory encoded
432
+ ) internal pure returns (TokenBridgeTransferWithPayloadEssentials memory twp) {
433
+ (twp, ) = decodeTransferWithPayloadEssentialsStructMem(encoded, 0, encoded.length);
434
+ }
435
+
436
+ function decodeTransferWithPayloadEssentialsMem(
437
+ bytes memory encoded,
438
+ uint offset,
439
+ uint length
440
+ ) internal pure returns (
441
+ uint256 normalizedAmount,
442
+ bytes32 tokenAddress,
443
+ uint16 tokenChainId,
444
+ bytes32 fromAddress,
445
+ bytes memory payload,
446
+ uint newOffset
447
+ ) { unchecked {
448
+ (normalizedAmount, tokenAddress, tokenChainId, offset) =
449
+ _decodeTransferCommonHeaderEssentialsMemUnchecked(encoded, offset, PAYLOAD_ID_TRANSFER_WITH_PAYLOAD);
450
+
451
+ offset += COMMON_TRANSFER_TO_ADDRESS_SIZE + COMMON_TRANSFER_TO_CHAIN_ID_SIZE;
452
+ (fromAddress, offset) = encoded.asBytes32MemUnchecked(offset);
453
+
454
+ offset.checkBound(length); //check for underflow
455
+ (payload, newOffset) = encoded.sliceMemUnchecked(offset, length - offset);
456
+
457
+ }}
458
+
459
+ function decodeTransferWithPayloadEssentialsStructMem(
460
+ bytes memory encoded,
461
+ uint offset,
462
+ uint length
463
+ ) internal pure returns (TokenBridgeTransferWithPayloadEssentials memory twp, uint newOffset) {
464
+ ( twp.normalizedAmount,
465
+ twp.tokenAddress,
466
+ twp.tokenChainId,
467
+ twp.fromAddress,
468
+ twp.payload,
469
+ newOffset
470
+ ) = decodeTransferWithPayloadEssentialsMem(encoded, offset, length);
471
+ }
472
+
473
+ // AttestMeta
474
+
475
+ function decodeAttestMetaCd(
476
+ bytes calldata encoded
477
+ ) internal pure returns (
478
+ bytes32 tokenAddress,
479
+ uint16 tokenChainId,
480
+ uint8 decimals,
481
+ bytes32 symbol,
482
+ bytes32 name
483
+ ) {
484
+ uint offset = 0;
485
+ uint8 payloadId;
486
+ (payloadId, offset) = encoded.asUint8CdUnchecked(offset);
487
+ checkPayloadId(payloadId, PAYLOAD_ID_ATTEST_META);
488
+ (tokenAddress, offset) = encoded.asBytes32CdUnchecked(offset);
489
+ (tokenChainId, offset) = encoded.asUint16CdUnchecked(offset);
490
+ (decimals, offset) = encoded.asUint8CdUnchecked(offset);
491
+ (symbol, offset) = encoded.asBytes32CdUnchecked(offset);
492
+ (name, offset) = encoded.asBytes32CdUnchecked(offset);
493
+ encoded.length.checkLength(offset);
494
+ }
495
+
496
+ function decodeAttestMetaStructCd(
497
+ bytes calldata encoded
498
+ ) internal pure returns (TokenBridgeAttestMeta memory attestMeta) {
499
+ ( attestMeta.tokenAddress,
500
+ attestMeta.tokenChainId,
501
+ attestMeta.decimals,
502
+ attestMeta.symbol,
503
+ attestMeta.name
504
+ ) = decodeAttestMetaCd(encoded);
505
+ }
506
+
507
+ function decodeAttestMetaMem(
508
+ bytes memory encoded
509
+ ) internal pure returns (
510
+ bytes32 tokenAddress,
511
+ uint16 tokenChainId,
512
+ uint8 decimals,
513
+ bytes32 symbol,
514
+ bytes32 name
515
+ ) {
516
+ uint offset = 0;
517
+ (tokenAddress, tokenChainId, decimals, symbol, name, offset) =
518
+ decodeAttestMetaMemUnchecked(encoded, offset);
519
+ encoded.length.checkLength(offset);
520
+ }
521
+
522
+ function decodeAttestMetaStructMem(
523
+ bytes memory encoded
524
+ ) internal pure returns (TokenBridgeAttestMeta memory attestMeta) {
525
+ (attestMeta, ) = decodeAttestMetaStructMemUnchecked(encoded, 0);
526
+ }
527
+
528
+ function decodeAttestMetaMemUnchecked(
529
+ bytes memory encoded,
530
+ uint offset
531
+ ) internal pure returns (
532
+ bytes32 tokenAddress,
533
+ uint16 tokenChainId,
534
+ uint8 decimals,
535
+ bytes32 symbol,
536
+ bytes32 name,
537
+ uint newOffset
538
+ ) {
539
+ uint8 payloadId;
540
+ (payloadId, offset) = encoded.asUint8MemUnchecked(offset);
541
+ checkPayloadId(payloadId, PAYLOAD_ID_ATTEST_META);
542
+ (tokenAddress, offset) = encoded.asBytes32MemUnchecked(offset);
543
+ (tokenChainId, offset) = encoded.asUint16MemUnchecked(offset);
544
+ (decimals, offset) = encoded.asUint8MemUnchecked(offset);
545
+ (symbol, offset) = encoded.asBytes32MemUnchecked(offset);
546
+ (name, offset) = encoded.asBytes32MemUnchecked(offset);
547
+ newOffset = offset;
548
+ }
549
+
550
+ function decodeAttestMetaStructMemUnchecked(
551
+ bytes memory encoded,
552
+ uint offset
553
+ ) internal pure returns (TokenBridgeAttestMeta memory attestMeta, uint newOffset) {
554
+ ( attestMeta.tokenAddress,
555
+ attestMeta.tokenChainId,
556
+ attestMeta.decimals,
557
+ attestMeta.symbol,
558
+ attestMeta.name,
559
+ newOffset
560
+ ) = decodeAttestMetaMemUnchecked(encoded, offset);
561
+ }
562
+
563
+ // ------------ Encoding ------------
564
+
565
+ function encodeTransfer(
566
+ uint256 normalizedAmount,
567
+ bytes32 tokenAddress,
568
+ uint16 tokenChainId,
569
+ bytes32 toAddress,
570
+ uint16 toChainId
571
+ ) internal pure returns (bytes memory encoded) {
572
+ return abi.encodePacked(
573
+ PAYLOAD_ID_TRANSFER,
574
+ normalizedAmount,
575
+ tokenAddress,
576
+ tokenChainId,
577
+ toAddress,
578
+ toChainId,
579
+ uint256(0) //add otherwise discarded fee field
580
+ );
581
+ }
582
+
583
+ function encode(TokenBridgeTransfer memory transfer) internal pure returns (bytes memory) {
584
+ return encodeTransfer(
585
+ transfer.normalizedAmount,
586
+ transfer.tokenAddress,
587
+ transfer.tokenChainId,
588
+ transfer.toAddress,
589
+ transfer.toChainId
590
+ );
591
+ }
592
+
593
+ function encodeTransferWithPayload(
594
+ uint256 normalizedAmount,
595
+ bytes32 tokenAddress,
596
+ uint16 tokenChainId,
597
+ bytes32 toAddress,
598
+ uint16 toChainId,
599
+ bytes32 fromAddress,
600
+ bytes memory payload
601
+ ) internal pure returns (bytes memory encoded) {
602
+ return abi.encodePacked(
603
+ PAYLOAD_ID_TRANSFER_WITH_PAYLOAD,
604
+ normalizedAmount,
605
+ tokenAddress,
606
+ tokenChainId,
607
+ toAddress,
608
+ toChainId,
609
+ fromAddress,
610
+ payload
611
+ );
612
+ }
613
+
614
+ function encode(TokenBridgeTransferWithPayload memory twp) internal pure returns (bytes memory) {
615
+ return encodeTransferWithPayload(
616
+ twp.normalizedAmount,
617
+ twp.tokenAddress,
618
+ twp.tokenChainId,
619
+ twp.toAddress,
620
+ twp.toChainId,
621
+ twp.fromAddress,
622
+ twp.payload
623
+ );
624
+ }
625
+
626
+ function encodeAttestMeta(
627
+ bytes32 tokenAddress,
628
+ uint16 tokenChainId,
629
+ uint8 decimals,
630
+ bytes32 symbol,
631
+ bytes32 name
632
+ ) internal pure returns (bytes memory encoded) {
633
+ return abi.encodePacked(
634
+ PAYLOAD_ID_ATTEST_META,
635
+ tokenAddress,
636
+ tokenChainId,
637
+ decimals,
638
+ symbol,
639
+ name
640
+ );
641
+ }
642
+
643
+ function encode(TokenBridgeAttestMeta memory attestMeta) internal pure returns (bytes memory) {
644
+ return encodeAttestMeta(
645
+ attestMeta.tokenAddress,
646
+ attestMeta.tokenChainId,
647
+ attestMeta.decimals,
648
+ attestMeta.symbol,
649
+ attestMeta.name
650
+ );
651
+ }
652
+
653
+ // ------------ Private ------------
654
+
655
+ function _decodeTransferCommonHeaderEssentialsCdUnchecked(
656
+ bytes calldata encoded,
657
+ uint8 expectedPayloadId
658
+ ) private pure returns (
659
+ uint256 normalizedAmount,
660
+ bytes32 tokenAddress,
661
+ uint16 tokenChainId,
662
+ uint newOffset
663
+ ) {
664
+ uint8 payloadId;
665
+ uint offset = 0;
666
+ (payloadId, offset) = encoded.asUint8CdUnchecked(offset);
667
+ checkPayloadId(payloadId, expectedPayloadId);
668
+ (normalizedAmount, offset) = encoded.asUint256CdUnchecked(offset);
669
+ (tokenAddress, offset) = encoded.asBytes32CdUnchecked(offset);
670
+ (tokenChainId, offset) = encoded.asUint16CdUnchecked(offset);
671
+ newOffset = offset;
672
+ }
673
+
674
+ function _decodeTransferCommonHeaderEssentialsMemUnchecked(
675
+ bytes memory encoded,
676
+ uint offset,
677
+ uint8 expectedPayloadId
678
+ ) private pure returns (
679
+ uint256 normalizedAmount,
680
+ bytes32 tokenAddress,
681
+ uint16 tokenChainId,
682
+ uint newOffset
683
+ ) {
684
+ uint8 payloadId;
685
+ (payloadId, offset) = encoded.asUint8MemUnchecked(offset);
686
+ checkPayloadId(payloadId, expectedPayloadId);
687
+ (normalizedAmount, offset) = encoded.asUint256MemUnchecked(offset);
688
+ (tokenAddress, offset) = encoded.asBytes32MemUnchecked(offset);
689
+ (tokenChainId, offset) = encoded.asUint16MemUnchecked(offset);
690
+ newOffset = offset;
691
+ }
692
+
693
+ function _decodeTransferCommonHeaderCdUnchecked(
694
+ bytes calldata encoded,
695
+ uint8 expectedPayloadId
696
+ ) private pure returns (
697
+ uint256 normalizedAmount,
698
+ bytes32 tokenAddress,
699
+ uint16 tokenChainId,
700
+ bytes32 toAddress,
701
+ uint16 toChainId,
702
+ uint newOffset
703
+ ) {
704
+ uint offset;
705
+ (
706
+ normalizedAmount,
707
+ tokenAddress,
708
+ tokenChainId,
709
+ offset
710
+ ) = _decodeTransferCommonHeaderEssentialsCdUnchecked(encoded, expectedPayloadId);
711
+ (toAddress, offset) = encoded.asBytes32CdUnchecked(offset);
712
+ (toChainId, offset) = encoded.asUint16CdUnchecked(offset);
713
+ newOffset = offset;
714
+ }
715
+
716
+ function _decodeTransferCommonHeaderMemUnchecked(
717
+ bytes memory encoded,
718
+ uint offset,
719
+ uint8 expectedPayloadId
720
+ ) private pure returns (
721
+ uint256 normalizedAmount,
722
+ bytes32 tokenAddress,
723
+ uint16 tokenChainId,
724
+ bytes32 toAddress,
725
+ uint16 toChainId,
726
+ uint newOffset
727
+ ) {
728
+ (
729
+ normalizedAmount,
730
+ tokenAddress,
731
+ tokenChainId,
732
+ offset
733
+ ) = _decodeTransferCommonHeaderEssentialsMemUnchecked(encoded, offset, expectedPayloadId);
734
+ (toAddress, offset) = encoded.asBytes32MemUnchecked(offset);
735
+ (toChainId, offset) = encoded.asUint16MemUnchecked(offset);
736
+ newOffset = offset;
737
+ }
738
+ }
739
+
740
+ using TokenBridgeMessageLib for TokenBridgeTransfer global;
741
+ using TokenBridgeMessageLib for TokenBridgeTransferWithPayload global;
742
+ using TokenBridgeMessageLib for TokenBridgeAttestMeta global;