@@ -12,7 +12,6 @@ import {ITokenMinter} from "src/interfaces/ITokenMinter.sol";
12
12
13
13
import {Utils} from "src/libraries/Utils.sol " ;
14
14
import {Deposit, WormholeCctpMessages} from "src/libraries/WormholeCctpMessages.sol " ;
15
- import {RedeemParameters, RedeemedDeposit} from "src/libraries/WormholeCctpStructs.sol " ;
16
15
17
16
abstract contract WormholeCctp {
18
17
using Utils for address ;
@@ -21,7 +20,19 @@ abstract contract WormholeCctp {
21
20
22
21
error InvalidVaa ();
23
22
error CallerNotMintRecipient (bytes32 , bytes32 );
24
- error CctpVaaMismatch ();
23
+ error CctpVaaMismatch (uint32 , uint32 , uint64 );
24
+
25
+ struct RedeemedDeposit {
26
+ bytes32 token;
27
+ uint256 amount;
28
+ bytes32 burnSource;
29
+ uint32 vaaTimestamp;
30
+ uint32 vaaNonce;
31
+ uint16 emitterChain;
32
+ bytes32 emitterAddress;
33
+ uint64 vaaSequence;
34
+ bytes32 vaaHash;
35
+ }
25
36
26
37
/**
27
38
* @notice Emitted when Circle-supported assets have been minted to the mintRecipient
@@ -95,10 +106,11 @@ abstract contract WormholeCctp {
95
106
);
96
107
}
97
108
98
- function verifyVaaAndMint (RedeemParameters calldata params )
99
- internal
100
- returns (RedeemedDeposit memory redeemed , bytes memory payload )
101
- {
109
+ function verifyVaaAndMint (
110
+ bytes calldata encodedCctpMessage ,
111
+ bytes calldata cctpAttestation ,
112
+ bytes calldata encodedVaa
113
+ ) internal returns (RedeemedDeposit memory redeemed , bytes memory payload ) {
102
114
Deposit memory deposit;
103
115
(
104
116
redeemed.vaaTimestamp,
@@ -110,7 +122,9 @@ abstract contract WormholeCctp {
110
122
deposit,
111
123
payload
112
124
) = _verifyVaaAndMint (
113
- params,
125
+ encodedCctpMessage,
126
+ cctpAttestation,
127
+ encodedVaa,
114
128
true // revertCustomErrors
115
129
);
116
130
@@ -120,7 +134,11 @@ abstract contract WormholeCctp {
120
134
redeemed.burnSource = deposit.burnSource;
121
135
}
122
136
123
- function verifyVaaAndMintLegacy (RedeemParameters calldata params )
137
+ function verifyVaaAndMintLegacy (
138
+ bytes calldata encodedCctpMessage ,
139
+ bytes calldata cctpAttestation ,
140
+ bytes calldata encodedVaa
141
+ )
124
142
internal
125
143
returns (
126
144
uint16 emitterChain ,
@@ -131,7 +149,9 @@ abstract contract WormholeCctp {
131
149
)
132
150
{
133
151
(,, emitterChain, emitterAddress,, vaaHash, deposit, payload) = _verifyVaaAndMint (
134
- params,
152
+ encodedCctpMessage,
153
+ cctpAttestation,
154
+ encodedVaa,
135
155
false // revertCustomErrors
136
156
);
137
157
}
@@ -148,7 +168,12 @@ abstract contract WormholeCctp {
148
168
149
169
// private
150
170
151
- function _verifyVaaAndMint (RedeemParameters calldata params , bool revertCustomErrors )
171
+ function _verifyVaaAndMint (
172
+ bytes calldata encodedCctpMessage ,
173
+ bytes calldata cctpAttestation ,
174
+ bytes calldata encodedVaa ,
175
+ bool revertCustomErrors
176
+ )
152
177
private
153
178
returns (
154
179
uint32 vaaTimestamp ,
@@ -163,7 +188,7 @@ abstract contract WormholeCctp {
163
188
{
164
189
// Parse and Verify VAA.
165
190
(IWormhole.VM memory vaa , bool valid , string memory reason ) =
166
- _wormhole.parseAndVerifyVM (params. encodedVaa);
191
+ _wormhole.parseAndVerifyVM (encodedVaa);
167
192
168
193
// Confirm that the core layer verified the message.
169
194
if (! valid) {
@@ -191,36 +216,39 @@ abstract contract WormholeCctp {
191
216
192
217
// Confirm that the caller passed the correct message pair.
193
218
{
194
- bytes memory encodedCctpMessage = params.cctpMessage;
195
-
196
219
uint32 sourceDomain;
197
220
uint32 targetDomain;
198
221
uint64 nonce;
199
222
200
- // NOTE: First four bytes is the CCTP message version.
201
223
assembly ("memory-safe" ) {
202
- // source domain is 4 bytes after the version
203
- sourceDomain := mload (add (encodedCctpMessage, 8 ))
204
- // target domain is 4 bytes after the source domain
205
- targetDomain := mload (add (encodedCctpMessage, 12 ))
206
- // nonce is 8 bytes after the target version
207
- nonce := mload (add (encodedCctpMessage, 20 ))
224
+ // NOTE: First four bytes is the CCTP message version.
225
+ let ptr := calldataload (encodedCctpMessage.offset)
226
+
227
+ // NOTE: There is no need to mask here because the types defined outside of this
228
+ // YUL block will already perform big-endian masking.
229
+
230
+ // Source domain is bytes 4..8, so shift 24 bytes to the right.
231
+ sourceDomain := shr (192 , ptr)
232
+ // Target domain is bytes 8..12, so shift 20 bytes to the right.
233
+ targetDomain := shr (160 , ptr)
234
+ // Nonce is bytes 12..20, so shift 12 bytes to the right.
235
+ nonce := shr (96 , ptr)
208
236
}
209
237
210
238
if (
211
239
deposit.sourceCctpDomain != sourceDomain || deposit.targetCctpDomain != targetDomain
212
240
|| deposit.cctpNonce != nonce
213
241
) {
214
242
if (revertCustomErrors) {
215
- revert CctpVaaMismatch ();
243
+ revert CctpVaaMismatch (sourceDomain, targetDomain, nonce );
216
244
} else {
217
245
_revertBuiltIn ("invalid message pair " );
218
246
}
219
247
}
220
248
}
221
249
222
250
// Call the circle bridge to mint tokens to the recipient.
223
- _messageTransmitter.receiveMessage (params.cctpMessage, params. cctpAttestation);
251
+ _messageTransmitter.receiveMessage (encodedCctpMessage, cctpAttestation);
224
252
225
253
// Overwrite the token address in the deposit with the local token address. We should trust
226
254
// that this getter will not return the zero address because the Token Minter will have
0 commit comments