@@ -127,6 +127,10 @@ contract Orchestrator is IOrchestrator, EIP712, CallContextChecker, ReentrancyGu
127127 /// This constant is a pun for "chain ID 0".
128128 uint16 public constant MULTICHAIN_NONCE_PREFIX = 0xc1d0 ;
129129
130+ /// @dev Nonce prefix to signal that the payload should use merkle verification.
131+ /// This constant is "mv" in hex.
132+ uint16 public constant MERKLE_VERIFICATION = 0x6D76 ;
133+
130134 /// @dev For ensuring that the remaining gas is sufficient for a self-call with
131135 /// overhead for cleaning up after the self-call. This also has an added benefit
132136 /// of preventing the censorship vector of calling `execute` in a very deep call-stack.
@@ -349,13 +353,11 @@ contract Orchestrator is IOrchestrator, EIP712, CallContextChecker, ReentrancyGu
349353 // Early skip the entire pay-verify-call workflow if the payer lacks tokens,
350354 // so that less gas is wasted when the Intent fails.
351355 // For multi chain mode, we skip this check, as the funding happens inside the self call.
352- if (! i.isMultichain && LibBit.and (i.paymentAmount != 0 , err == 0 )) {
353- if (TokenTransferLib.balanceOf (i.paymentToken, payer) < i.paymentAmount) {
354- err = PaymentError.selector ;
356+ if (TokenTransferLib.balanceOf (i.paymentToken, payer) < i.paymentAmount) {
357+ err = PaymentError.selector ;
355358
356- if (flags == _SIMULATION_MODE_FLAG) {
357- revert PaymentError ();
358- }
359+ if (flags == _SIMULATION_MODE_FLAG) {
360+ revert PaymentError ();
359361 }
360362 }
361363
@@ -476,7 +478,8 @@ contract Orchestrator is IOrchestrator, EIP712, CallContextChecker, ReentrancyGu
476478
477479 bool isValid;
478480 bytes32 keyHash;
479- if (i.isMultichain) {
481+
482+ if (i.nonce >> 240 == MERKLE_VERIFICATION) {
480483 // For multi chain intents, we have to verify using merkle sigs.
481484 (isValid, keyHash) = _verifyMerkleSig (digest, eoa, i.signature);
482485
@@ -754,40 +757,35 @@ contract Orchestrator is IOrchestrator, EIP712, CallContextChecker, ReentrancyGu
754757 function _computeDigest (SignedCall calldata p ) internal view virtual returns (bytes32 ) {
755758 bool isMultichain = p.nonce >> 240 == MULTICHAIN_NONCE_PREFIX;
756759 // To avoid stack-too-deep. Faster than a regular Solidity array anyways.
757- bytes32 [] memory f = EfficientHashLib.malloc (5 );
760+ bytes32 [] memory f = EfficientHashLib.malloc (4 );
758761 f.set (0 , SIGNED_CALL_TYPEHASH);
759- f.set (1 , LibBit.toUint (isMultichain));
760- f.set (2 , uint160 (p.eoa));
761- f.set (3 , _executionDataHash (p.executionData));
762- f.set (4 , p.nonce);
762+ f.set (1 , uint160 (p.eoa));
763+ f.set (2 , _executionDataHash (p.executionData));
764+ f.set (3 , p.nonce);
763765
764766 return isMultichain ? _hashTypedDataSansChainId (f.hash ()) : _hashTypedData (f.hash ());
765767 }
766768
767769 /// @dev Computes the EIP712 digest for the Intent.
768- /// If the the nonce starts with `MULTICHAIN_NONCE_PREFIX`,
769- /// the digest will be computed without the chain ID.
770- /// Otherwise, the digest will be computed with the chain ID.
771770 function _computeDigest (Intent calldata i ) internal view virtual returns (bytes32 ) {
772- bool isMultichain = i.nonce >> 240 == MULTICHAIN_NONCE_PREFIX;
773-
774771 // To avoid stack-too-deep. Faster than a regular Solidity array anyways.
775- bytes32 [] memory f = EfficientHashLib.malloc (13 );
772+ bytes32 [] memory f = EfficientHashLib.malloc (12 );
776773 f.set (0 , INTENT_TYPEHASH);
777- f.set (1 , LibBit.toUint (isMultichain));
778- f.set (2 , uint160 (i.eoa));
779- f.set (3 , _executionDataHash (i.executionData));
780- f.set (4 , i.nonce);
781- f.set (5 , uint160 (i.payer));
782- f.set (6 , uint160 (i.paymentToken));
783- f.set (7 , i.paymentMaxAmount);
784- f.set (8 , i.combinedGas);
785- f.set (9 , _encodedArrHash (i.encodedPreCalls));
786- f.set (10 , _encodedArrHash (i.encodedFundTransfers));
787- f.set (11 , uint160 (i.settler));
788- f.set (12 , i.expiry);
789-
790- return isMultichain ? _hashTypedDataSansChainId (f.hash ()) : _hashTypedData (f.hash ());
774+ f.set (1 , uint160 (i.eoa));
775+ f.set (2 , _executionDataHash (i.executionData));
776+ f.set (3 , i.nonce);
777+ f.set (4 , uint160 (i.payer));
778+ f.set (5 , uint160 (i.paymentToken));
779+ f.set (6 , i.paymentMaxAmount);
780+ f.set (7 , i.combinedGas);
781+ f.set (8 , _encodedArrHash (i.encodedPreCalls));
782+ f.set (9 , _encodedArrHash (i.encodedFundTransfers));
783+ f.set (10 , uint160 (i.settler));
784+ f.set (11 , i.expiry);
785+
786+ return i.nonce >> 240 == MULTICHAIN_NONCE_PREFIX
787+ ? _hashTypedDataSansChainId (f.hash ())
788+ : _hashTypedData (f.hash ());
791789 }
792790
793791 /// @dev Helper function to return the hash of the `execuctionData`.
0 commit comments