@@ -279,14 +279,35 @@ contract UCS03Zkgm is
279
279
}
280
280
}
281
281
282
+ function onRecvIntentPacket (
283
+ address caller ,
284
+ IBCPacket calldata packet ,
285
+ address relayer ,
286
+ bytes calldata relayerMsg
287
+ ) external virtual override onlyIBC whenNotPaused returns (bytes memory ) {
288
+ return _processReceive (caller, packet, relayer, relayerMsg, true );
289
+ }
290
+
282
291
function onRecvPacket (
283
292
address caller ,
284
293
IBCPacket calldata packet ,
285
294
address relayer ,
286
295
bytes calldata relayerMsg
287
296
) external virtual override onlyIBC whenNotPaused returns (bytes memory ) {
297
+ return _processReceive (caller, packet, relayer, relayerMsg, false );
298
+ }
299
+
300
+ function _processReceive (
301
+ address caller ,
302
+ IBCPacket calldata packet ,
303
+ address relayer ,
304
+ bytes calldata relayerMsg ,
305
+ bool intent
306
+ ) internal returns (bytes memory ) {
288
307
(bool success , bytes memory returnData ) = address (this ).call (
289
- abi.encodeCall (this .execute, (caller, packet, relayer, relayerMsg))
308
+ abi.encodeCall (
309
+ this .execute, (caller, packet, relayer, relayerMsg, intent)
310
+ )
290
311
);
291
312
// Avoid gas-starvation trick. Enforce a minimum for griefing relayers.
292
313
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/bd325d56b4c62c9c5c1aff048c37c6bb18ac0290/contracts/metatx/MinimalForwarder.sol#L58-L68
@@ -325,7 +346,8 @@ contract UCS03Zkgm is
325
346
address caller ,
326
347
IBCPacket calldata ibcPacket ,
327
348
address relayer ,
328
- bytes calldata relayerMsg
349
+ bytes calldata relayerMsg ,
350
+ bool intent
329
351
) public returns (bytes memory ) {
330
352
// Only callable through the onRecvPacket endpoint.
331
353
if (msg .sender != address (this )) {
@@ -339,7 +361,8 @@ contract UCS03Zkgm is
339
361
relayerMsg,
340
362
zkgmPacket.salt,
341
363
zkgmPacket.path,
342
- zkgmPacket.instruction
364
+ zkgmPacket.instruction,
365
+ intent
343
366
);
344
367
}
345
368
@@ -350,7 +373,8 @@ contract UCS03Zkgm is
350
373
bytes calldata relayerMsg ,
351
374
bytes32 salt ,
352
375
uint256 path ,
353
- Instruction calldata instruction
376
+ Instruction calldata instruction ,
377
+ bool intent
354
378
) internal returns (bytes memory ) {
355
379
if (instruction.opcode == ZkgmLib.OP_FUNGIBLE_ASSET_ORDER) {
356
380
if (instruction.version != ZkgmLib.INSTR_VERSION_1) {
@@ -359,7 +383,7 @@ contract UCS03Zkgm is
359
383
FungibleAssetOrder calldata order =
360
384
ZkgmLib.decodeFungibleAssetOrder (instruction.operand);
361
385
return _executeFungibleAssetOrder (
362
- caller, ibcPacket, relayer, relayerMsg, path, order
386
+ caller, ibcPacket, relayer, relayerMsg, path, order, intent
363
387
);
364
388
} else if (instruction.opcode == ZkgmLib.OP_BATCH) {
365
389
if (instruction.version > ZkgmLib.INSTR_VERSION_0) {
@@ -372,7 +396,8 @@ contract UCS03Zkgm is
372
396
relayerMsg,
373
397
salt,
374
398
path,
375
- ZkgmLib.decodeBatch (instruction.operand)
399
+ ZkgmLib.decodeBatch (instruction.operand),
400
+ intent
376
401
);
377
402
} else if (instruction.opcode == ZkgmLib.OP_FORWARD) {
378
403
if (instruction.version > ZkgmLib.INSTR_VERSION_0) {
@@ -385,7 +410,8 @@ contract UCS03Zkgm is
385
410
salt,
386
411
path,
387
412
instruction.version,
388
- ZkgmLib.decodeForward (instruction.operand)
413
+ ZkgmLib.decodeForward (instruction.operand),
414
+ intent
389
415
);
390
416
} else if (instruction.opcode == ZkgmLib.OP_MULTIPLEX) {
391
417
if (instruction.version > ZkgmLib.INSTR_VERSION_0) {
@@ -398,7 +424,8 @@ contract UCS03Zkgm is
398
424
relayerMsg,
399
425
path,
400
426
salt,
401
- ZkgmLib.decodeMultiplex (instruction.operand)
427
+ ZkgmLib.decodeMultiplex (instruction.operand),
428
+ intent
402
429
);
403
430
} else {
404
431
revert ZkgmLib.ErrUnknownOpcode ();
@@ -412,7 +439,8 @@ contract UCS03Zkgm is
412
439
bytes calldata relayerMsg ,
413
440
bytes32 salt ,
414
441
uint256 path ,
415
- Batch calldata batch
442
+ Batch calldata batch ,
443
+ bool intent
416
444
) internal returns (bytes memory ) {
417
445
uint256 l = batch.instructions.length ;
418
446
bytes [] memory acks = new bytes [](l);
@@ -425,7 +453,8 @@ contract UCS03Zkgm is
425
453
relayerMsg,
426
454
ZkgmLib.deriveBatchSalt (i, salt),
427
455
path,
428
- instruction
456
+ instruction,
457
+ intent
429
458
);
430
459
// We should have the guarantee that the acks are non empty because
431
460
// the only instructions allowed in a batch are multiplex and
@@ -448,8 +477,19 @@ contract UCS03Zkgm is
448
477
bytes32 salt ,
449
478
uint256 path ,
450
479
uint8 version ,
451
- Forward calldata forward
480
+ Forward calldata forward ,
481
+ bool intent
452
482
) internal returns (bytes memory ) {
483
+ // We cannot allow market makers to fill packets containing forward
484
+ // instruction. This would allow them to submit of a proof and fill via the
485
+ // protocol on destination for a fake forward.
486
+
487
+ // Instead, they must first fill on destination the orders, awaits finality
488
+ // to settle the forward, then cascade acknowledge.
489
+ if (intent) {
490
+ revert ZkgmLib.ErrInvalidMarketMakerOperation ();
491
+ }
492
+
453
493
(uint256 tailPath , uint32 previousDestinationChannelId ) =
454
494
ZkgmLib.dequeueChannelFromPath (forward.path);
455
495
(uint256 continuationPath , uint32 nextSourceChannelId ) =
@@ -508,20 +548,34 @@ contract UCS03Zkgm is
508
548
bytes calldata relayerMsg ,
509
549
uint256 path ,
510
550
bytes32 salt ,
511
- Multiplex calldata multiplex
551
+ Multiplex calldata multiplex ,
552
+ bool intent
512
553
) internal returns (bytes memory ) {
513
554
address contractAddress = address (bytes20 (multiplex.contractAddress));
514
555
if (! multiplex.eureka) {
515
- IZkgmable (contractAddress).onZkgm (
516
- caller,
517
- path,
518
- ibcPacket.sourceChannelId,
519
- ibcPacket.destinationChannelId,
520
- multiplex.sender,
521
- multiplex.contractCalldata,
522
- relayer,
523
- relayerMsg
524
- );
556
+ if (intent) {
557
+ IZkgmable (contractAddress).onIntentZkgm (
558
+ caller,
559
+ path,
560
+ ibcPacket.sourceChannelId,
561
+ ibcPacket.destinationChannelId,
562
+ multiplex.sender,
563
+ multiplex.contractCalldata,
564
+ relayer,
565
+ relayerMsg
566
+ );
567
+ } else {
568
+ IZkgmable (contractAddress).onZkgm (
569
+ caller,
570
+ path,
571
+ ibcPacket.sourceChannelId,
572
+ ibcPacket.destinationChannelId,
573
+ multiplex.sender,
574
+ multiplex.contractCalldata,
575
+ relayer,
576
+ relayerMsg
577
+ );
578
+ }
525
579
return abi.encode (ZkgmLib.ACK_SUCCESS);
526
580
} else {
527
581
IBCPacket memory multiplexIbcPacket = IBCPacket ({
@@ -533,8 +587,17 @@ contract UCS03Zkgm is
533
587
timeoutHeight: ibcPacket.timeoutHeight,
534
588
timeoutTimestamp: ibcPacket.timeoutTimestamp
535
589
});
536
- bytes memory acknowledgement = IIBCModuleRecv (contractAddress)
537
- .onRecvPacket (caller, multiplexIbcPacket, relayer, relayerMsg);
590
+ bytes memory acknowledgement;
591
+ if (intent) {
592
+ acknowledgement = IIBCModuleRecv (contractAddress)
593
+ .onRecvIntentPacket (
594
+ caller, multiplexIbcPacket, relayer, relayerMsg
595
+ );
596
+ } else {
597
+ acknowledgement = IIBCModuleRecv (contractAddress).onRecvPacket (
598
+ caller, multiplexIbcPacket, relayer, relayerMsg
599
+ );
600
+ }
538
601
if (acknowledgement.length == 0 ) {
539
602
revert ZkgmLib.ErrAsyncMultiplexUnsupported ();
540
603
}
@@ -695,13 +758,26 @@ contract UCS03Zkgm is
695
758
address relayer ,
696
759
bytes calldata relayerMsg ,
697
760
uint256 path ,
698
- FungibleAssetOrder calldata order
761
+ FungibleAssetOrder calldata order ,
762
+ bool intent
699
763
) internal returns (bytes memory ) {
764
+ address quoteToken = address (bytes20 (order.quoteToken));
765
+ address payable receiver = payable (address (bytes20 (order.receiver)));
766
+
767
+ // For intent packets, the protocol is not allowed to provide any fund
768
+ // as the packet has not been checked for membership poof. Instead, we
769
+ // know the market maker will be repaid on the source chain, if and only
770
+ // if the currently executing packet hash had been registered as sent on
771
+ // the source. In other words, the market maker is unable to lie.
772
+ if (intent) {
773
+ return _marketMakerFill (
774
+ caller, relayerMsg, quoteToken, receiver, order.quoteAmount
775
+ );
776
+ }
777
+
700
778
(address wrappedToken , bytes32 wrappedTokenSalt ) = _predictWrappedToken (
701
779
path, ibcPacket.destinationChannelId, order.baseToken
702
780
);
703
- address quoteToken = address (bytes20 (order.quoteToken));
704
- address payable receiver = payable (address (bytes20 (order.receiver)));
705
781
bool baseAmountCoversQuoteAmount = order.baseAmount >= order.quoteAmount;
706
782
if (quoteToken == wrappedToken && baseAmountCoversQuoteAmount) {
707
783
_rateLimit (quoteToken, order.quoteAmount);
@@ -739,6 +815,9 @@ contract UCS03Zkgm is
739
815
false
740
816
);
741
817
} else {
818
+ // We also allow market makers to fill orders after finality. This
819
+ // allow orders that combines protocol and mm filling (wrapped vs
820
+ // non wrapped assets).
742
821
return _marketMakerFill (
743
822
caller, relayerMsg, quoteToken, receiver, order.quoteAmount
744
823
);
0 commit comments