@@ -17,6 +17,16 @@ contract DelegateCallTarget {
1717 function revertAlways () external pure {
1818 revert ("Target revert " );
1919 }
20+
21+ function revertWithCustomError () external pure {
22+ revert CustomError ("Custom error message " );
23+ }
24+
25+ function panicAlways () external pure {
26+ assert (false );
27+ }
28+
29+ error CustomError (string message );
2030}
2131
2232// Contract that uses delegateCallChecked
@@ -30,6 +40,14 @@ contract DelegateCallChecker {
3040 function delegateCallRevert (address target ) external {
3141 delegateCallChecked (target, abi.encodeWithSelector (DelegateCallTarget.revertAlways.selector ));
3242 }
43+
44+ function delegateCallCustomError (address target ) external {
45+ delegateCallChecked (target, abi.encodeWithSelector (DelegateCallTarget.revertWithCustomError.selector ));
46+ }
47+
48+ function delegateCallPanic (address target ) external {
49+ delegateCallChecked (target, abi.encodeWithSelector (DelegateCallTarget.panicAlways.selector ));
50+ }
3351}
3452
3553contract CallUtilsAnvil is Test {
@@ -59,10 +77,36 @@ contract CallUtilsAnvil is Test {
5977 DelegateCallTarget target = new DelegateCallTarget ();
6078 DelegateCallChecker checker = new DelegateCallChecker ();
6179
62- vm.expectRevert ("CallUtils: delegatecall failed " );
80+ // Verify that the actual error message is propagated
81+ vm.expectRevert ("Target revert " );
6382 checker.delegateCallRevert (address (target));
6483 }
6584
85+ function testDelegateCallChecked_CustomError () public {
86+ DelegateCallTarget target = new DelegateCallTarget ();
87+ DelegateCallChecker checker = new DelegateCallChecker ();
88+
89+ // Verify that custom errors are properly propagated
90+ vm.expectRevert (
91+ abi.encodeWithSelector (
92+ DelegateCallTarget.CustomError.selector ,
93+ "Custom error message "
94+ )
95+ );
96+ checker.delegateCallCustomError (address (target));
97+ }
98+
99+ function testDelegateCallChecked_Panic () public {
100+ DelegateCallTarget target = new DelegateCallTarget ();
101+ DelegateCallChecker checker = new DelegateCallChecker ();
102+
103+ // Verify that panic errors are properly propagated with error information
104+ // Panic code 0x01 is for assert(false)
105+ // The error should be formatted as "CallUtils: target panicked: 0x01"
106+ vm.expectRevert ("CallUtils: target panicked: 0x01 " );
107+ checker.delegateCallPanic (address (target));
108+ }
109+
66110 // TODO this is a hard fuzzing case, because we need to know if there is a case that:
67111 // 1. CallUtils.isValidAbiEncodedBytes returns true
68112 // 2. and abi.decode reverts
0 commit comments