Skip to content

Commit 186bca2

Browse files
committed
add additional test cases
1 parent c899b94 commit 186bca2

File tree

5 files changed

+173
-5
lines changed

5 files changed

+173
-5
lines changed

test/EIP7702Proxy/delegate.t.sol

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,45 @@ contract DelegateTest is EIP7702ProxyBase {
3838
MockImplementation(payable(_eoa)).mockFunction();
3939
// Success is just completing the call without revert
4040
}
41+
42+
/**
43+
* Tests that complex return data (non-binary) is correctly delegated
44+
*/
45+
function testDelegatesComplexReturnData() public {
46+
bytes memory testData = hex"deadbeef";
47+
// Call returnBytesData with test data
48+
bytes memory returnedData = MockImplementation(payable(_eoa))
49+
.returnBytesData(testData);
50+
51+
// Verify the complex return data matches expected format
52+
assertEq(
53+
returnedData,
54+
testData,
55+
"Complex return data should be correctly delegated"
56+
);
57+
}
58+
59+
/**
60+
* Tests that delegate call fails if read operation fails
61+
*/
62+
function testDelegateFailsOnReadFailure() public {
63+
vm.expectRevert("MockRevert");
64+
MockImplementation(payable(_eoa)).revertingFunction();
65+
}
66+
67+
/**
68+
* Tests that delegate call fails if write operation fails
69+
*/
70+
function testDelegateFailsOnWriteFailure() public {
71+
// Try to call mockFunction as non-owner
72+
vm.prank(address(0xBAD));
73+
vm.expectRevert(MockImplementation.Unauthorized.selector);
74+
MockImplementation(payable(_eoa)).mockFunction();
75+
76+
// Verify state was not changed
77+
assertFalse(
78+
MockImplementation(payable(_eoa)).mockFunctionCalled(),
79+
"State should not change when write fails"
80+
);
81+
}
4182
}

test/EIP7702Proxy/initialize.t.sol

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.23;
33

44
import {EIP7702ProxyBase} from "../base/EIP7702ProxyBase.sol";
55
import {EIP7702Proxy} from "../../src/EIP7702Proxy.sol";
6-
import {MockImplementation} from "../mocks/MockImplementation.sol";
6+
import {MockImplementation, RevertingInitializerMockImplementation} from "../mocks/MockImplementation.sol";
77
import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
88

99
contract InitializeTest is EIP7702ProxyBase {
@@ -73,4 +73,53 @@ contract InitializeTest is EIP7702ProxyBase {
7373
vm.expectRevert(EIP7702Proxy.InvalidSignature.selector);
7474
EIP7702Proxy(_eoa).initialize(initArgs, signature);
7575
}
76+
77+
function testRevertsWhenInitializerDelegatecallFails() public {
78+
// Deploy reverting implementation
79+
_implementation = new RevertingInitializerMockImplementation();
80+
_initSelector = RevertingInitializerMockImplementation
81+
.initialize
82+
.selector;
83+
84+
// Deploy proxy normally first to get the correct immutable values
85+
_proxy = new EIP7702Proxy(address(_implementation), _initSelector);
86+
87+
// Get the proxy's runtime code
88+
bytes memory proxyCode = address(_proxy).code;
89+
90+
// Etch the proxy code at the EOA's address
91+
vm.etch(_eoa, proxyCode);
92+
93+
// Try to initialize with valid signature but reverting implementation
94+
bytes memory initArgs = _createInitArgs(_newOwner);
95+
bytes memory signature = _signInitData(_EOA_PRIVATE_KEY, initArgs);
96+
97+
vm.expectRevert("InitializerReverted");
98+
EIP7702Proxy(_eoa).initialize(initArgs, signature);
99+
}
100+
101+
function testRevertsWhenSignatureReplayedWithDifferentProxy() public {
102+
// Get signature for first proxy
103+
bytes memory initArgs = _createInitArgs(_newOwner);
104+
bytes memory signature = _signInitData(_EOA_PRIVATE_KEY, initArgs);
105+
106+
// Deploy a second proxy with same implementation
107+
address payable secondProxy = payable(address(0xBEEF));
108+
_deployProxy(secondProxy);
109+
110+
// Try to use same signature with different proxy
111+
vm.expectRevert(EIP7702Proxy.InvalidSignature.selector);
112+
EIP7702Proxy(secondProxy).initialize(initArgs, signature);
113+
}
114+
115+
function testRevertsWhenSignatureReplayedWithDifferentArgs() public {
116+
// Get signature for first initialization args
117+
bytes memory initArgs = _createInitArgs(_newOwner);
118+
bytes memory signature = _signInitData(_EOA_PRIVATE_KEY, initArgs);
119+
120+
// Try to use same signature with different args
121+
bytes memory differentArgs = _createInitArgs(address(0xBEEF));
122+
vm.expectRevert(EIP7702Proxy.InvalidSignature.selector);
123+
EIP7702Proxy(_eoa).initialize(differentArgs, signature);
124+
}
76125
}

test/EIP7702Proxy/isValidSignature.t.sol

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.23;
33

44
import {EIP7702ProxyBase} from "../base/EIP7702ProxyBase.sol";
55
import {EIP7702Proxy} from "../../src/EIP7702Proxy.sol";
6-
import {MockImplementation, FailingSignatureImplementation} from "../mocks/MockImplementation.sol";
6+
import {MockImplementation, FailingSignatureImplementation, RevertingIsValidSignatureImplementation} from "../mocks/MockImplementation.sol";
77
import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
88

99
/**
@@ -65,7 +65,7 @@ abstract contract IsValidSignatureTestBase is EIP7702ProxyBase {
6565
}
6666

6767
/**
68-
* @dev Tests isValidSignature behavior with failing implementation
68+
* @dev Tests isValidSignature behavior when returning failure value from implementation isValidSignature
6969
*/
7070
contract FailingImplementationTest is IsValidSignatureTestBase {
7171
function setUp() public override {
@@ -110,7 +110,7 @@ contract FailingImplementationTest is IsValidSignatureTestBase {
110110
}
111111

112112
/**
113-
* @dev Tests isValidSignature behavior with succeeding implementation
113+
* @dev Tests isValidSignature behavior when returning success value from implementation isValidSignature
114114
*/
115115
contract SucceedingImplementationTest is IsValidSignatureTestBase {
116116
function setUp() public override {
@@ -157,3 +157,38 @@ contract SucceedingImplementationTest is IsValidSignatureTestBase {
157157
);
158158
}
159159
}
160+
161+
/**
162+
* @dev Tests isValidSignature behavior when reverting in implementation isValidSignature
163+
*/
164+
contract RevertingImplementationTest is IsValidSignatureTestBase {
165+
function setUp() public override {
166+
// Override base setup to use RevertingIsValidSignatureImplementation
167+
_implementation = new RevertingIsValidSignatureImplementation();
168+
_initSelector = MockImplementation.initialize.selector;
169+
170+
_eoa = payable(vm.addr(_EOA_PRIVATE_KEY));
171+
_newOwner = payable(vm.addr(_NEW_OWNER_PRIVATE_KEY));
172+
173+
// Deploy and setup proxy
174+
_proxy = new EIP7702Proxy(address(_implementation), _initSelector);
175+
bytes memory proxyCode = address(_proxy).code;
176+
vm.etch(_eoa, proxyCode);
177+
178+
// Initialize
179+
bytes memory initArgs = _createInitArgs(_newOwner);
180+
bytes memory signature = _signInitData(_EOA_PRIVATE_KEY, initArgs);
181+
EIP7702Proxy(_eoa).initialize(initArgs, signature);
182+
183+
super.setUp();
184+
}
185+
186+
function expectedInvalidSignatureResult()
187+
internal
188+
pure
189+
override
190+
returns (bytes4)
191+
{
192+
return ERC1271_FAIL_VALUE;
193+
}
194+
}

test/EIP7702Proxy/upgradeToAndCall.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {MockImplementation} from "../mocks/MockImplementation.sol";
77

88
/**
99
* @title UpgradeToAndCallTest
10-
* @dev Tests upgradeability functionality of EIP7702Proxy
10+
* @dev Tests ERC-1967 upgradeability functionality of EIP7702Proxy
1111
*/
1212
contract UpgradeToAndCallTest is EIP7702ProxyBase {
1313
MockImplementation newImplementation;

test/mocks/MockImplementation.sol

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ contract MockImplementation is UUPSUpgradeable {
6363
function _authorizeUpgrade(
6464
address
6565
) internal view virtual override onlyOwner {}
66+
67+
/**
68+
* @dev Mock function that returns arbitrary bytes data
69+
* @param data The data to return
70+
* @return The input data (to verify delegation preserves data)
71+
*/
72+
function returnBytesData(
73+
bytes memory data
74+
) public pure returns (bytes memory) {
75+
return data;
76+
}
77+
78+
/**
79+
* @dev Mock function that always reverts
80+
*/
81+
function revertingFunction() public pure {
82+
revert("MockRevert");
83+
}
6684
}
6785

6886
/**
@@ -78,3 +96,28 @@ contract FailingSignatureImplementation is MockImplementation {
7896
return 0xffffffff;
7997
}
8098
}
99+
100+
/**
101+
* @title RevertingIsValidSignatureImplementation
102+
* @dev Mock implementation that always reverts during signature validation
103+
*/
104+
contract RevertingIsValidSignatureImplementation is MockImplementation {
105+
/// @dev Always reverts during signature validation
106+
function isValidSignature(
107+
bytes32,
108+
bytes calldata
109+
) external pure override returns (bytes4) {
110+
revert("SignatureValidationFailed");
111+
}
112+
}
113+
114+
/**
115+
* @title RevertingInitializerMockImplementation
116+
* @dev Mock implementation that always reverts on initialization
117+
*/
118+
contract RevertingInitializerMockImplementation is MockImplementation {
119+
/// @dev Always reverts on initialization
120+
function initialize(address) public pure override {
121+
revert("InitializerReverted");
122+
}
123+
}

0 commit comments

Comments
 (0)