1
- import { ethers } from "ethers " ;
1
+ import { CircleBridge , UniversalAddress } from "@wormhole-foundation/sdk-definitions " ;
2
2
3
3
export type Cctp = {
4
4
version : number ;
@@ -13,9 +13,9 @@ export type Cctp = {
13
13
// Taken from https://developers.circle.com/stablecoins/docs/message-format.
14
14
export class CctpMessage {
15
15
cctp : Cctp ;
16
- message : Buffer ;
16
+ message : CctpTokenBurnMessage ;
17
17
18
- constructor ( cctp : Cctp , message : Buffer ) {
18
+ constructor ( cctp : Cctp , message : CctpTokenBurnMessage ) {
19
19
this . cctp = cctp ;
20
20
this . message = message ;
21
21
}
@@ -30,31 +30,60 @@ export class CctpMessage {
30
30
31
31
static decode ( buf : Readonly < Buffer > ) : CctpMessage {
32
32
const version = buf . readUInt32BE ( 0 ) ;
33
- const sourceDomain = buf . readUInt32BE ( 4 ) ;
34
- const destinationDomain = buf . readUInt32BE ( 8 ) ;
35
- const nonce = buf . readBigUInt64BE ( 12 ) ;
36
- const sender = Array . from ( buf . slice ( 20 , 52 ) ) ;
37
- const recipient = Array . from ( buf . slice ( 52 , 84 ) ) ;
38
- const targetCaller = Array . from ( buf . slice ( 84 , 116 ) ) ;
39
- const message = buf . subarray ( 116 ) ;
33
+
34
+ const [ msg ] = CircleBridge . deserialize ( new Uint8Array ( buf ) ) ;
35
+ const {
36
+ sourceDomain,
37
+ destinationDomain,
38
+ nonce,
39
+ sender,
40
+ recipient,
41
+ destinationCaller,
42
+ payload,
43
+ } = msg ;
44
+
45
+ const { burnToken, mintRecipient, amount, messageSender } = payload ;
46
+ const header : Cctp = {
47
+ version,
48
+ sourceDomain,
49
+ destinationDomain,
50
+ nonce,
51
+ sender : Array . from ( sender . toUint8Array ( ) ) ,
52
+ recipient : Array . from ( recipient . toUint8Array ( ) ) ,
53
+ targetCaller : Array . from ( destinationCaller . toUint8Array ( ) ) ,
54
+ } ;
40
55
41
56
return new CctpMessage (
42
- {
57
+ header ,
58
+ new CctpTokenBurnMessage (
59
+ header ,
43
60
version ,
44
- sourceDomain,
45
- destinationDomain,
46
- nonce,
47
- sender,
48
- recipient,
49
- targetCaller,
50
- } ,
51
- message ,
61
+ Array . from ( burnToken . toUint8Array ( ) ) ,
62
+ Array . from ( mintRecipient . toUint8Array ( ) ) ,
63
+ amount ,
64
+ Array . from ( messageSender . toUint8Array ( ) ) ,
65
+ ) ,
52
66
) ;
53
67
}
54
68
55
69
encode ( ) : Buffer {
56
70
const { cctp, message } = this ;
57
- return Buffer . concat ( [ encodeCctp ( cctp ) , message ] ) ;
71
+ return Buffer . from (
72
+ CircleBridge . serialize ( {
73
+ sourceDomain : cctp . sourceDomain ,
74
+ destinationDomain : cctp . destinationDomain ,
75
+ nonce : cctp . nonce ,
76
+ sender : new UniversalAddress ( new Uint8Array ( cctp . sender ) ) ,
77
+ recipient : new UniversalAddress ( new Uint8Array ( cctp . recipient ) ) ,
78
+ destinationCaller : new UniversalAddress ( new Uint8Array ( cctp . targetCaller ) ) ,
79
+ payload : {
80
+ burnToken : new UniversalAddress ( new Uint8Array ( message . burnTokenAddress ) ) ,
81
+ mintRecipient : new UniversalAddress ( new Uint8Array ( message . mintRecipient ) ) ,
82
+ amount : message . amount ,
83
+ messageSender : new UniversalAddress ( new Uint8Array ( message . sender ) ) ,
84
+ } ,
85
+ } ) ,
86
+ ) ;
58
87
}
59
88
}
60
89
@@ -91,63 +120,11 @@ export class CctpTokenBurnMessage {
91
120
}
92
121
93
122
static decode ( buf : Readonly < Buffer > ) : CctpTokenBurnMessage {
94
- const { cctp, message } = CctpMessage . decode ( buf ) ;
95
- const version = message . readUInt32BE ( 0 ) ;
96
- const burnTokenAddress = Array . from ( message . subarray ( 4 , 36 ) ) ;
97
- const mintRecipient = Array . from ( message . subarray ( 36 , 68 ) ) ;
98
- const amount = BigInt ( ethers . BigNumber . from ( message . subarray ( 68 , 100 ) ) . toString ( ) ) ;
99
- const sender = Array . from ( message . subarray ( 100 , 132 ) ) ;
100
-
101
- return new CctpTokenBurnMessage (
102
- cctp ,
103
- version ,
104
- burnTokenAddress ,
105
- mintRecipient ,
106
- amount ,
107
- sender ,
108
- ) ;
123
+ const { message } = CctpMessage . decode ( buf ) ;
124
+ return message ;
109
125
}
110
126
111
127
encode ( ) : Buffer {
112
- const buf = Buffer . alloc ( 132 ) ;
113
-
114
- const { cctp, version, burnTokenAddress, mintRecipient, amount, sender } = this ;
115
-
116
- let offset = 0 ;
117
- offset = buf . writeUInt32BE ( version , offset ) ;
118
- buf . set ( burnTokenAddress , offset ) ;
119
- offset += 32 ;
120
- buf . set ( mintRecipient , offset ) ;
121
- offset += 32 ;
122
-
123
- // Special handling w/ uint256. This value will most likely encoded in < 32 bytes, so we
124
- // jump ahead by 32 and subtract the length of the encoded value.
125
- const encodedAmount = ethers . utils . arrayify ( ethers . BigNumber . from ( amount . toString ( ) ) ) ;
126
- buf . set ( encodedAmount , ( offset += 32 ) - encodedAmount . length ) ;
127
-
128
- buf . set ( sender , offset ) ;
129
- offset += 32 ;
130
-
131
- return Buffer . concat ( [ encodeCctp ( cctp ) , buf ] ) ;
128
+ return new CctpMessage ( this . cctp , this ) . encode ( ) ;
132
129
}
133
130
}
134
-
135
- function encodeCctp ( cctp : Cctp ) : Buffer {
136
- const buf = Buffer . alloc ( 116 ) ;
137
-
138
- const { version, sourceDomain, destinationDomain, nonce, sender, recipient, targetCaller } =
139
- cctp ;
140
-
141
- let offset = 0 ;
142
- offset = buf . writeUInt32BE ( version , offset ) ;
143
- offset = buf . writeUInt32BE ( sourceDomain , offset ) ;
144
- offset = buf . writeUInt32BE ( destinationDomain , offset ) ;
145
- offset = buf . writeBigUInt64BE ( nonce , offset ) ;
146
- buf . set ( sender , offset ) ;
147
- offset += 32 ;
148
- buf . set ( recipient , offset ) ;
149
- offset += 32 ;
150
- buf . set ( targetCaller , offset ) ;
151
-
152
- return buf ;
153
- }
0 commit comments