@@ -39,6 +39,7 @@ import {
39
39
} from "../_spoke-pool-periphery" ;
40
40
import { getUniversalSwapAndBridgeAddress } from "../_swap-and-bridge" ;
41
41
import axios , { AxiosRequestHeaders } from "axios" ;
42
+ import { encodeActionCalls } from "../swap/_utils" ;
42
43
43
44
export type CrossSwapType =
44
45
( typeof CROSS_SWAP_TYPE ) [ keyof typeof CROSS_SWAP_TYPE ] ;
@@ -190,14 +191,19 @@ export function buildExactInputBridgeTokenMessage(
190
191
crossSwap : CrossSwap ,
191
192
outputAmount : BigNumber
192
193
) {
193
- const transferActions = crossSwap . isOutputNative
194
+ const unwrapActions = crossSwap . isOutputNative
194
195
? // WETH unwrap to ETH
195
196
[
196
197
{
197
198
target : crossSwap . outputToken . address ,
198
199
callData : encodeWethWithdrawCalldata ( outputAmount ) ,
199
200
value : "0" ,
200
201
} ,
202
+ ]
203
+ : [ ] ;
204
+ const transferActions = crossSwap . isOutputNative
205
+ ? // ETH transfer
206
+ [
201
207
{
202
208
target : crossSwap . recipient ,
203
209
callData : "0x" ,
@@ -212,10 +218,20 @@ export function buildExactInputBridgeTokenMessage(
212
218
value : "0" ,
213
219
} ,
214
220
] ;
221
+ const embeddedActions = crossSwap . embeddedActions
222
+ ? encodeActionCalls (
223
+ crossSwap . embeddedActions ,
224
+ crossSwap . outputToken . chainId
225
+ )
226
+ : [ ] ;
227
+
215
228
return buildMulticallHandlerMessage ( {
216
229
fallbackRecipient : getFallbackRecipient ( crossSwap ) ,
217
230
actions : [
218
- ...transferActions ,
231
+ // unwrap weth if output token is native
232
+ ...unwrapActions ,
233
+ // execute destination actions or transfer output tokens
234
+ ...( embeddedActions . length > 0 ? embeddedActions : transferActions ) ,
219
235
// drain remaining bridgeable output tokens from MultiCallHandler contract
220
236
{
221
237
target : getMultiCallHandlerAddress ( crossSwap . outputToken . chainId ) ,
@@ -235,14 +251,19 @@ export function buildExactInputBridgeTokenMessage(
235
251
* tokens are refunded to the depositor.
236
252
*/
237
253
export function buildExactOutputBridgeTokenMessage ( crossSwap : CrossSwap ) {
238
- const transferActions = crossSwap . isOutputNative
254
+ const unwrapActions = crossSwap . isOutputNative
239
255
? // WETH unwrap to ETH
240
256
[
241
257
{
242
258
target : crossSwap . outputToken . address ,
243
259
callData : encodeWethWithdrawCalldata ( crossSwap . amount ) ,
244
260
value : "0" ,
245
261
} ,
262
+ ]
263
+ : [ ] ;
264
+ const transferActions = crossSwap . isOutputNative
265
+ ? // ETH transfer
266
+ [
246
267
{
247
268
target : crossSwap . recipient ,
248
269
callData : "0x" ,
@@ -260,10 +281,20 @@ export function buildExactOutputBridgeTokenMessage(crossSwap: CrossSwap) {
260
281
value : "0" ,
261
282
} ,
262
283
] ;
284
+ const embeddedActions = crossSwap . embeddedActions
285
+ ? encodeActionCalls (
286
+ crossSwap . embeddedActions ,
287
+ crossSwap . outputToken . chainId
288
+ )
289
+ : [ ] ;
290
+
263
291
return buildMulticallHandlerMessage ( {
264
292
fallbackRecipient : getFallbackRecipient ( crossSwap ) ,
265
293
actions : [
266
- ...transferActions ,
294
+ // unwrap weth if output token is native
295
+ ...unwrapActions ,
296
+ // execute destination actions or transfer output tokens
297
+ ...( embeddedActions . length > 0 ? embeddedActions : transferActions ) ,
267
298
// drain remaining bridgeable output tokens from MultiCallHandler contract
268
299
{
269
300
target : getMultiCallHandlerAddress ( crossSwap . outputToken . chainId ) ,
@@ -285,7 +316,7 @@ export function buildMinOutputBridgeTokenMessage(
285
316
crossSwap : CrossSwap ,
286
317
unwrapAmount ?: BigNumber
287
318
) {
288
- const transferActions = crossSwap . isOutputNative
319
+ const unwrapActions = crossSwap . isOutputNative
289
320
? // WETH unwrap to ETH
290
321
[
291
322
{
@@ -295,18 +326,42 @@ export function buildMinOutputBridgeTokenMessage(
295
326
) ,
296
327
value : "0" ,
297
328
} ,
329
+ ]
330
+ : [ ] ;
331
+ const transferActions = crossSwap . isOutputNative
332
+ ? // ETH transfer
333
+ [
298
334
{
299
335
target : crossSwap . recipient ,
300
336
callData : "0x" ,
301
337
value : ( unwrapAmount || crossSwap . amount ) . toString ( ) ,
302
338
} ,
303
339
]
304
340
: // ERC-20 token transfer
305
- [ ] ;
341
+ [
342
+ {
343
+ target : crossSwap . outputToken . address ,
344
+ callData : encodeTransferCalldata (
345
+ crossSwap . recipient ,
346
+ unwrapAmount || crossSwap . amount
347
+ ) ,
348
+ value : "0" ,
349
+ } ,
350
+ ] ;
351
+
352
+ const embeddedActions = crossSwap . embeddedActions
353
+ ? encodeActionCalls (
354
+ crossSwap . embeddedActions ,
355
+ crossSwap . outputToken . chainId
356
+ )
357
+ : [ ] ;
306
358
return buildMulticallHandlerMessage ( {
307
359
fallbackRecipient : getFallbackRecipient ( crossSwap ) ,
308
360
actions : [
309
- ...transferActions ,
361
+ // unwrap weth if output token is native
362
+ ...unwrapActions ,
363
+ // execute destination actions or transfer output tokens
364
+ ...( embeddedActions . length > 0 ? embeddedActions : transferActions ) ,
310
365
// drain remaining bridgeable output tokens from MultiCallHandler contract
311
366
{
312
367
target : getMultiCallHandlerAddress ( crossSwap . outputToken . chainId ) ,
@@ -454,11 +509,14 @@ export function buildDestinationSwapCrossChainMessage({
454
509
swapTxn . to === "0x0" && swapTxn . data === "0x0" && swapTxn . value === "0x0"
455
510
) ;
456
511
457
- let transferActions : {
512
+ type Action = {
458
513
target : string ;
459
514
callData : string ;
460
515
value : string ;
461
- } [ ] = [ ] ;
516
+ } ;
517
+
518
+ let transferActions : Action [ ] = [ ] ;
519
+ let unwrapActions : Action [ ] = [ ] ;
462
520
463
521
// If output token is native, we need to unwrap WETH before sending it to the
464
522
// recipient. This is because we only handle WETH in the destination swap.
@@ -467,12 +525,14 @@ export function buildDestinationSwapCrossChainMessage({
467
525
( crossSwap . type === AMOUNT_TYPE . EXACT_OUTPUT ||
468
526
crossSwap . type === AMOUNT_TYPE . MIN_OUTPUT )
469
527
) {
470
- transferActions = [
528
+ unwrapActions = [
471
529
{
472
530
target : crossSwap . outputToken . address ,
473
531
callData : encodeWethWithdrawCalldata ( crossSwap . amount ) ,
474
532
value : "0" ,
475
533
} ,
534
+ ] ;
535
+ transferActions = [
476
536
{
477
537
target : crossSwap . recipient ,
478
538
callData : "0x" ,
@@ -515,14 +575,16 @@ export function buildDestinationSwapCrossChainMessage({
515
575
] ;
516
576
} else if ( crossSwap . type === AMOUNT_TYPE . EXACT_INPUT ) {
517
577
if ( crossSwap . isOutputNative ) {
518
- transferActions = [
578
+ unwrapActions = [
519
579
{
520
580
target : crossSwap . outputToken . address ,
521
581
callData : encodeWethWithdrawCalldata (
522
582
destinationSwapQuote . minAmountOut
523
583
) ,
524
584
value : "0" ,
525
585
} ,
586
+ ] ;
587
+ transferActions = [
526
588
{
527
589
target : crossSwap . recipient ,
528
590
callData : "0x" ,
@@ -551,6 +613,11 @@ export function buildDestinationSwapCrossChainMessage({
551
613
value : swapTxn . value ,
552
614
} ) ) ;
553
615
616
+ const embeddedActions =
617
+ crossSwap . embeddedActions && ! isIndicativeQuote
618
+ ? encodeActionCalls ( crossSwap . embeddedActions , destinationSwapChainId )
619
+ : [ ] ;
620
+
554
621
return buildMulticallHandlerMessage ( {
555
622
fallbackRecipient : getFallbackRecipient ( crossSwap ) ,
556
623
actions : [
@@ -565,8 +632,10 @@ export function buildDestinationSwapCrossChainMessage({
565
632
} ,
566
633
// swap bridgeable output token -> cross swap output token
567
634
...swapActions ,
568
- // transfer output tokens to recipient
569
- ...transferActions ,
635
+ // unwrap weth if output token is native
636
+ ...unwrapActions ,
637
+ // transfer output tokens to recipient or execute destination actions
638
+ ...( embeddedActions . length > 0 ? embeddedActions : transferActions ) ,
570
639
// drain remaining bridgeable output tokens from MultiCallHandler contract
571
640
{
572
641
target : getMultiCallHandlerAddress ( destinationSwapChainId ) ,
@@ -576,6 +645,20 @@ export function buildDestinationSwapCrossChainMessage({
576
645
) ,
577
646
value : "0" ,
578
647
} ,
648
+ // drain remaining swap output tokens from MultiCallHandler contract
649
+ // (only needed when there's embedded actions, otherwise the drain call is already part of transferActions)
650
+ ...( embeddedActions . length > 0
651
+ ? [
652
+ {
653
+ target : getMultiCallHandlerAddress ( destinationSwapChainId ) ,
654
+ callData : encodeDrainCalldata (
655
+ crossSwap . outputToken . address ,
656
+ crossSwap . refundAddress ?? crossSwap . depositor
657
+ ) ,
658
+ value : "0" ,
659
+ } ,
660
+ ]
661
+ : [ ] ) ,
579
662
] ,
580
663
} ) ;
581
664
}
0 commit comments