Skip to content

Commit 3a4c292

Browse files
committed
fix: nits, add tests for corrupted static fields
1 parent 37edf58 commit 3a4c292

File tree

1 file changed

+178
-47
lines changed

1 file changed

+178
-47
lines changed

test/Account.t.sol

Lines changed: 178 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)