@@ -508,80 +508,220 @@ contract AccountTest is BaseTest {
508508 assertEq (keysCount137, 2 , "Keys should be added on chain 137 " );
509509 }
510510
511+ /**
512+ *
513+ * Calldata layout (32-byte words; left column = byte offset from start)
514+ *
515+ * bytes
516+ * pos 0x
517+ * 0: 0000000000000000000000000000000000000000000000000000000000000b20 - bytes length prefix (=2848)
518+ * 32: 0000000000000000000000000000000000000000000000000000000000000020 - Intent start offset
519+ * 64: 0000000000000000000000005c6bd1597b1411cce0e79a0841fd11073120493b - eoa
520+ * 96: 0000000000000000000000000000000000000000000000000000000000000280 - executionData offset
521+ * 128: c1d0000000000000000000000000000000000000000000000000000000000000 - nonce
522+ * 160: 0000000000000000000000000000000000000000000000000000000000000000 - payer
523+ * 192: 0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b - paymentToken
524+ * 224: 000000000000000000000000000000000000000000000000000000008e95aab8 - paymentMaxAmount
525+ * 256: 0000000000000000000000000000000000000000000000000000000000989680 - combinedGas
526+ * 288: 00000000000000000000000000000000000000000000000000000000000002e0 - encodedPreCalls offset
527+ * 320: 00000000000000000000000000000000000000000000000000000000000009e0 - encodedFundTransfers offset
528+ * 352: 0000000000000000000000000000000000000000000000000000000000000000 - settler
529+ * 384: 0000000000000000000000000000000000000000000000000000000000000000 - expiry
530+ * 416: 0000000000000000000000000000000000000000000000000000000000000000 - isMultichain
531+ * 448: 0000000000000000000000000000000000000000000000000000000000000000 - funder
532+ * 480: 0000000000000000000000000000000000000000000000000000000000000a00 - funderSignature offset
533+ * 512: 0000000000000000000000000000000000000000000000000000000000000a20 - settlerContext offset
534+ * 544: 000000000000000000000000000000000000000000000000000000008e95aab8 - paymentAmount
535+ * 576: 0000000000000000000000000000000000000000000000000000000000000000 - paymentReceipt
536+ * 608: 0000000000000000000000000000000000000000000000000000000000000a40 - signature offset
537+ * 640: 0000000000000000000000000000000000000000000000000000000000000ae0 - paymentSignature offset
538+ * 672: 0000000000000000000000000000000000000000000000000000000000000000 - supportedAccountImplementation
539+ *
540+ */
541+
542+ // Test 1: eoa corruption
543+ function testPayWithAllCorruptedEOAFieldOfIntent () public {
544+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
545+ assembly {
546+ mstore (add (maliciousCalldata, 64 ), 0x10000000000000000 ) // 2^64 (strictly greater than 2^64-1)
547+ }
548+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("PaymentError() " )));
549+ }
550+
551+ // Test 2: nonce corruption
552+ function testPayWithAllCorruptedNonceFieldOfIntent () public {
553+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
554+ assembly {
555+ mstore (add (maliciousCalldata, 128 ), 0x10000000000000001 ) // 2^64 + 1
556+ }
557+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerificationError() " )));
558+ }
559+
560+ // Test 3: payer corruption
561+ function testPayWithAllCorruptedPayerFieldOfIntent () public {
562+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
563+ assembly {
564+ mstore (add (maliciousCalldata, 160 ), 0x10000000000000002 ) // 2^64 + 2
565+ }
566+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("PaymentError() " )));
567+ }
568+
569+ // Test 4: paymentToken corruption
570+ function testPayWithAllCorruptedPaymentTokenFieldOfIntent () public {
571+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
572+ assembly {
573+ mstore (add (maliciousCalldata, 192 ), 0x10000000000000003 ) // 2^64 + 3
574+ }
575+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("PaymentError() " )));
576+ }
577+
578+ // Test 5: paymentMaxAmount corruption
579+ function testPayWithAllCorruptedPaymentMaxAmountFieldOfIntent () public {
580+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
581+ assembly {
582+ mstore (add (maliciousCalldata, 224 ), 0x10000000000000004 ) // 2^64 + 4
583+ }
584+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerificationError() " )));
585+ }
586+
587+ // Test 6: combinedGas corruption
588+ function testPayWithAllCorruptedCombinedGasFieldOfIntent () public {
589+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
590+ assembly {
591+ mstore (add (maliciousCalldata, 256 ), 0x00 ) // 0 gas limit
592+ }
593+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerifiedCallError() " )));
594+ }
595+
596+ // Test 7: settler corruption
597+ function testPayWithAllCorruptedSettlerFieldOfIntent () public {
598+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
599+ assembly {
600+ mstore (add (maliciousCalldata, 352 ), 0x10000000000000005 ) // 2^64 + 5
601+ }
602+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerificationError() " )));
603+ }
604+
605+ // Test 8: expiry corruption
606+ function testPayWithAllCorruptedExpiryFieldOfIntent () public {
607+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
608+ assembly {
609+ mstore (add (maliciousCalldata, 384 ), 0x10000000000000006 ) // 2^64 + 6
610+ }
611+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerificationError() " )));
612+ }
613+
614+ // Test 9: isMultichain corruption
615+ function testPayWithAllCorruptedIsMultichainFieldOfIntent () public {
616+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
617+ assembly {
618+ mstore (add (maliciousCalldata, 416 ), 0x01 ) // true flag with non-multichain intent
619+ }
620+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerifiedCallError() " )));
621+ }
622+
623+ // Test 10: funder corruption
624+ function testPayWithAllCorruptedFunderFieldOfIntent () public {
625+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
626+ assembly {
627+ // corupting with garbage address as returns 0x00000000 with 0x10000000000000008 (2^64 + 8)
628+ mstore (
629+ add (maliciousCalldata, 448 ),
630+ 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
631+ )
632+ }
633+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerifiedCallError() " )));
634+ }
635+
636+ // Test 11: paymentAmount corruption
637+ function testPayWithAllCorruptedPaymentAmountFieldOfIntent () public {
638+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
639+ assembly {
640+ let paymentMaxAmount := mload (add (maliciousCalldata, 224 ))
641+ // corrupt paymentAmount with paymentMaxAmount + 1
642+ mstore (add (maliciousCalldata, 544 ), add (paymentMaxAmount, 1 ))
643+ }
644+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("PaymentError() " )));
645+ }
646+
647+ // Test 12: paymentReceipt corruption
648+ function testPayWithAllCorruptedPaymentReceiptFieldOfIntent () public {
649+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
650+ // corrupt paymentReceipt with garbage address as returns 0x00000000 with 0x10000000000000009 (2^64 + 9)
651+ assembly {
652+ mstore (
653+ add (maliciousCalldata, 576 ),
654+ 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
655+ )
656+ }
657+ assertEq (oc.execute (maliciousCalldata), bytes4 (keccak256 ("VerifiedCallError() " )));
658+ }
659+
660+ // Test 13: supportedAccountImplementation corruption
661+ function testPayWithAllCorruptedSupportedAccountImplementationFieldOfIntent () public {
662+ bytes memory maliciousCalldata = _createIntentOnMainnet ();
663+ assembly {
664+ mstore (add (maliciousCalldata, 672 ), 0x10000000000000009 ) // 2^64 + 9
665+ }
666+ assertEq (
667+ oc.execute (maliciousCalldata), bytes4 (keccak256 ("UnsupportedAccountImplementation() " ))
668+ );
669+ }
670+
511671 function testPayWithFiveCorruptedFieldOffsetsOfIntent () public {
512672 bool success;
513673 bytes memory returnData;
514674
515- console. log ( " Test 1: Main Intent struct offset corruption " );
675+ // Test 1: Main Intent struct offset corruption
516676 bytes memory maliciousCalldata = _createIntentOnMainnet ();
677+ uint256 len;
517678 assembly {
518- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
519- // CORRUPT MAIN OFFSET (Bytes 0-31) - Points to Intent struct start
520- mstore (dataPtr, 0x10000000000000000 ) // 2^64 (strictly greater than 2^64-1)
679+ mstore (add (maliciousCalldata, 32 ), 0x10000000000000000 ) // 2^64 (strictly greater than 2^64-1)
521680 }
522681 (success, returnData) =
523682 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
524683 assertEq (success, false );
525684
526- console. log ( " Test 2: executionData offset corruption " );
685+ // Test 2: executionData offset corruption
527686 maliciousCalldata = _createIntentOnMainnet ();
528687 assembly {
529- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
530- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
531- // executionData offset (bytes 64-95 relative to start, or 32-63 in Intent struct)
532- mstore (add (intentPtr, 32 ), 0x10000000000000001 ) // 2^64 + 1
688+ mstore (add (maliciousCalldata, 96 ), 0x10000000000000001 ) // 2^64 + 1
533689 }
534- // assertEq(oc.execute(maliciousCalldata), bytes4(keccak256("VerifiedCallError()")));
535690 (success, returnData) =
536691 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
537692 assertEq (success, false );
538693
539- console. log ( " Test 3: encodedPreCalls offset corruption " );
694+ // Test 3: encodedPreCalls offset corruption
540695 maliciousCalldata = _createIntentOnMainnet ();
541696 assembly {
542- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
543- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
544- // encodedPreCalls offset (bytes 256-287 relative to start, or 224-255 in Intent struct)
545- mstore (add (intentPtr, 224 ), 0x10000000000000002 ) // 2^64 + 2
697+ mstore (add (maliciousCalldata, 288 ), 0x10000000000000002 ) // 2^64 + 2
546698 }
547- // assertEq(oc.execute(maliciousCalldata), bytes4(keccak256("VerifiedCallError()")));
548699 (success, returnData) =
549700 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
550701 assertEq (success, false );
551702
552- console. log ( " Test 4: encodedFundTransfers offset corruption " );
703+ // Test 4: encodedFundTransfers offset corruption
553704 maliciousCalldata = _createIntentOnMainnet ();
554705 assembly {
555- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
556- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
557- // encodedFundTransfers offset (bytes 288-319 relative to start, or 256-287 in Intent struct)
558- mstore (add (intentPtr, 256 ), 0x10000000000000003 ) // 2^64 + 3
706+ mstore (add (maliciousCalldata, 320 ), 0x10000000000000003 ) // 2^64 + 3
559707 }
560- // assertEq(oc.execute(maliciousCalldata), bytes4(keccak256("VerifiedCallError()")));
561708 (success, returnData) =
562709 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
563710 assertEq (success, false );
564711
565- console. log ( " Test 5: funderSignature offset corruption " );
712+ // Test 5: funderSignature offset corruption
566713 maliciousCalldata = _createIntentOnMainnet ();
567714 assembly {
568- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
569- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
570- // funderSignature offset (bytes 448-479 relative to start, or 416-447 in Intent struct)
571- mstore (add (intentPtr, 416 ), 0x10000000000000004 ) // 2^64 + 4
715+ mstore (add (maliciousCalldata, 480 ), 0x10000000000000004 ) // 2^64 + 4
572716 }
573- // assertEq(oc.execute(maliciousCalldata), bytes4(keccak256("VerifiedCallError()")));
574717 (success, returnData) =
575718 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
576719 assertEq (success, false );
577720
578- console. log ( " Test 6: signature offset corruption " );
721+ // Test 6: signature offset corruption
579722 maliciousCalldata = _createIntentOnMainnet ();
580723 assembly {
581- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
582- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
583- // signature offset (bytes 576-607 relative to start, or 544-575 in Intent struct)
584- mstore (add (intentPtr, 544 ), 0x10000000000000005 ) // 2^64 + 5
724+ mstore (add (maliciousCalldata, 608 ), 0x10000000000000005 ) // 2^64 + 5
585725 }
586726 (success, returnData) =
587727 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
@@ -705,15 +845,11 @@ contract AccountTest is BaseTest {
705845 u.signature = _eoaSig (d.privateKey, digest);
706846 u.paymentSignature = _eoaSig (payer.privateKey, digest);
707847
708- console. log ( " Test 7: paymentSignature offset corruption " );
848+ // Test 7: paymentSignature offset corruption
709849 bytes memory maliciousCalldata = abi.encode (u);
710850 assembly {
711- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
712- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
713- // paymentSignature offset (bytes 608-639 relative to start, or 576-607 in Intent struct)
714- mstore (add (intentPtr, 576 ), 0x10000000000000006 ) // 2^64 + 6
851+ mstore (add (maliciousCalldata, 640 ), 0x10000000000000006 ) // 2^64 + 6
715852 }
716-
717853 (bool success , bytes memory returnData ) =
718854 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
719855 assertEq (success, false );
@@ -925,17 +1061,12 @@ contract AccountTest is BaseTest {
9251061 // Relay funds the user account, and the intended execution happens.
9261062 t.encodedIntents[0 ] = abi.encode (t.outputIntent);
9271063
928- console. log ( " Test 8: settlerContext offset corruption " );
1064+ // Test 8: settlerContext offset corruption
9291065 bytes memory maliciousCalldata = t.encodedIntents[0 ];
9301066 assembly {
931- let dataPtr := add (maliciousCalldata, 0x20 ) // Skip bytes length prefix
932- let intentPtr := add (dataPtr, 0x20 ) // Points to start of Intent struct
933- // settlerContext offset (bytes 480-511 relative to start, or 448-479 in Intent struct)
934- mstore (add (intentPtr, 448 ), 0x10000000000000007 ) // 2^64 + 7
1067+ mstore (add (maliciousCalldata, 512 ), 0x10000000000000007 ) // 2^64 + 7
9351068 }
936-
937- // assertEq(oc.execute(maliciousCalldata), bytes4(keccak256("VerifiedCallError()")));
938- (bool success , bytes memory returnData ) =
1069+ (bool success ,) =
9391070 address (oc).call (abi.encodeWithSignature ("execute(bytes) " , maliciousCalldata));
9401071 assertEq (success, false );
9411072 }
0 commit comments