@@ -3,8 +3,12 @@ pragma solidity ^0.8.20;
33
44import { Test } from "forge-std/Test.sol " ;
55import { UUPSProxy } from "@tsxo/libsol/proxy/UUPS/UUPSProxy.sol " ;
6+ import { ERC1967Logic } from "@tsxo/libsol/proxy/ERC1967/ERC1967Logic.sol " ;
67import { UUPSCounterMock, UUPSCounterV2Mock } from "@tsxo/libsol/mocks/proxy/UUPS/UUPSImplementationMock.sol " ;
7- import { console } from "forge-std/console.sol " ;
8+ import {
9+ NonCompliantContract,
10+ WrongImplementationSlotContract
11+ } from "@tsxo/libsol/mocks/proxy/UUPS/UUPSNonCompliantMock.sol " ;
812
913interface TestEvents {
1014 event Upgraded (address indexed impl );
@@ -29,28 +33,34 @@ contract UUPSTest is Test, TestEvents {
2933
3034 function setUp () public {
3135 bytes memory initData = abi.encodeWithSignature ("initialize() " );
36+
3237 impl = new UUPSCounterMock ();
3338 implV2 = new UUPSCounterV2Mock ();
34-
3539 proxy = new UUPSProxy (address (impl), initData);
40+
3641 proxied = UUPSCounterMock (payable (address (proxy)));
3742 }
3843
3944 // -------------------------------------------------------------------------
40- // Tests
45+ // Proxy Construction Tests
46+
47+ function test_ProxyConstructor_RejectsNonERC1822CompliantContracts () public {
48+ bytes4 err = ERC1967Logic .ERC1967Logic__UpgradeFailed .selector ;
4149
42- function test_ProxyConstructor_ERC1822Compliant () public {
4350 address wrongSlot = address (new WrongImplementationSlotContract ());
4451 address nonCompliant = address (new NonCompliantContract ());
4552
46- vm.expectRevert ();
53+ vm.expectRevert (err );
4754 new UUPSProxy (wrongSlot, "" );
4855
4956 vm.expectRevert ();
5057 new UUPSProxy (nonCompliant, "" );
5158 }
5259
53- function test_ProxyInitialization () public {
60+ // -------------------------------------------------------------------------
61+ // Proxy Initialization Tests
62+
63+ function test_ProxyInitialization () public view {
5464 bytes memory countCall = abi.encodeWithSignature ("count() " );
5565 (bool success , bytes memory data ) = address (proxy).staticcall (countCall);
5666 uint256 count = abi.decode (data, (uint256 ));
@@ -59,7 +69,10 @@ contract UUPSTest is Test, TestEvents {
5969 assertEq (count, 0 );
6070 }
6171
62- function test_ProxyCalls () public {
72+ // -------------------------------------------------------------------------
73+ // Basic Functionality Tests
74+
75+ function test_ProxyCalls_DelegateToImplementation () public {
6376 proxied.increment ();
6477 assertEq (proxied.count (), 1 );
6578
@@ -72,7 +85,7 @@ contract UUPSTest is Test, TestEvents {
7285 assertEq (impl.count (), 0 );
7386 }
7487
75- function test_ProxyDelegatedCalls () public {
88+ function test_ProxyCalls_HandlesLowLevelCalls () public {
7689 bytes memory countCall = abi.encodeWithSignature ("count() " );
7790 bytes memory incCall = abi.encodeWithSignature ("increment() " );
7891 bytes memory decCall = abi.encodeWithSignature ("decrement() " );
@@ -118,6 +131,9 @@ contract UUPSTest is Test, TestEvents {
118131 assertFalse (success);
119132 }
120133
134+ // -------------------------------------------------------------------------
135+ // Ether Handling Tests
136+
121137 function test_ProxyEtherHandling () public {
122138 bytes memory fundCall = abi.encodeWithSignature ("fundMe() " );
123139 address user = address (0x1234 );
@@ -147,6 +163,9 @@ contract UUPSTest is Test, TestEvents {
147163 vm.stopPrank ();
148164 }
149165
166+ // -------------------------------------------------------------------------
167+ // Upgrade Tests
168+
150169 function test_Upgrade () public {
151170 proxied.setCount (5 );
152171 assertEq (proxied.count (), 5 );
@@ -194,7 +213,7 @@ contract UUPSTest is Test, TestEvents {
194213 assertEq (proxiedV2.count (), 5 );
195214 }
196215
197- function test_FailedUpgradeNotERC1822Compliant () public {
216+ function test_FailedUpgrade_NotERC1822Compliant () public {
198217 address nonCompliant = address (new NonCompliantContract ());
199218
200219 bytes memory upgradeCall = abi.encodeWithSignature ("upgradeToAndCall(address,bytes) " , nonCompliant, "" );
@@ -203,7 +222,7 @@ contract UUPSTest is Test, TestEvents {
203222 assertFalse (success);
204223 }
205224
206- function test_FailedUpgradeWrongImplementationSlot () public {
225+ function test_FailedUpgrade_WrongImplementationSlot () public {
207226 address wrongSlot = address (new WrongImplementationSlotContract ());
208227
209228 bytes memory upgradeCall = abi.encodeWithSignature ("upgradeToAndCall(address,bytes) " , wrongSlot, "" );
@@ -212,7 +231,7 @@ contract UUPSTest is Test, TestEvents {
212231 assertFalse (success);
213232 }
214233
215- function test_FailedUpgradeUnauthorized () public {
234+ function test_FailedUpgrade_Unauthorized () public {
216235 address attacker = address (0x5678 );
217236 vm.startPrank (attacker);
218237
@@ -224,32 +243,75 @@ contract UUPSTest is Test, TestEvents {
224243 vm.stopPrank ();
225244 }
226245
227- function test_ProxiableUUID_DirectCallSucceeds () public {
246+ // -------------------------------------------------------------------------
247+ // Call Context
248+
249+ function test_ProxiableUUID_DirectCallSucceeds () public view {
228250 bytes32 actualSlot = impl.proxiableUUID ();
229251 assertEq (actualSlot, IMPLEMENTATION_SLOT);
230252 }
231253
232- function test_ProxiableUUID_ProxiedCallReverts () public {
254+ function test_ProxiableUUID_ProxiedCallReverts () public view {
233255 bytes memory proxiableUUIDCall = abi.encodeWithSignature ("proxiableUUID() " );
234256
235257 (bool success ,) = address (proxy).staticcall (proxiableUUIDCall);
236258 assertFalse (success);
237259 }
238260
239- function test_UpgradeToAndCall_CallReverts () public {
261+ function test_UpgradeToAndCall_DirectCallReverts () public {
240262 address tempImpl = address (new UUPSCounterV2Mock ());
241263
242264 vm.expectRevert ();
243265 impl.upgradeToAndCall (tempImpl, "" );
244266 }
245- }
246267
247- /// @dev Does not implement proxiableUUID.
248- contract NonCompliantContract { }
268+ // -------------------------------------------------------------------------
269+ // Fuzz Tests
249270
250- /// @dev Returns the wrong implementation slot.
251- contract WrongImplementationSlotContract {
252- function proxiableUUID () external pure returns (bytes32 ) {
253- return bytes32 (keccak256 ("WRONG_IMPLEMENTATION_SLOT " ));
271+ function testFuzz_SetCount (uint256 newCount ) public {
272+ proxied.setCount (newCount);
273+ assertEq (impl.count (), 0 );
274+ assertEq (proxied.count (), newCount);
275+ }
276+
277+ function testFuzz_MultipleUpgradesPreserveState (uint256 startCount ) public {
278+ proxied.setCount (startCount);
279+ assertEq (proxied.count (), startCount);
280+
281+ bytes memory initCall = abi.encodeWithSignature ("markAsUpgraded() " );
282+ bytes memory upgradeCall = abi.encodeWithSignature ("upgradeToAndCall(address,bytes) " , address (implV2), initCall);
283+
284+ (bool success ,) = address (proxy).call (upgradeCall);
285+ assertTrue (success);
286+
287+ UUPSCounterV2Mock proxiedV2 = UUPSCounterV2Mock (payable (address (proxy)));
288+ assertEq (proxiedV2.count (), startCount);
289+ assertTrue (proxiedV2.upgraded ());
290+
291+ UUPSCounterV2Mock implV3 = new UUPSCounterV2Mock ();
292+
293+ upgradeCall = abi.encodeWithSignature ("upgradeToAndCall(address,bytes) " , address (implV3), initCall);
294+ (success,) = address (proxy).call (upgradeCall);
295+ assertTrue (success);
296+
297+ UUPSCounterV2Mock proxiedV3 = UUPSCounterV2Mock (payable (address (proxy)));
298+ assertEq (proxiedV3.count (), startCount);
299+ assertTrue (proxiedV3.upgraded ());
300+ }
301+
302+ function testFuzz_EtherHandling (uint256 amount ) public {
303+ vm.assume (amount > 0 && amount < 10 ether);
304+
305+ (bool success ,) = address (proxy).call { value: amount }("" );
306+ assertTrue (success);
307+ assertEq (address (proxy).balance, amount);
308+ }
309+
310+ // -------------------------------------------------------------------------
311+ // Invariant Tests
312+
313+ function invariant_ImplementationSlotMatchesProxiableUUID () public view {
314+ bytes32 actualSlot = impl.proxiableUUID ();
315+ assertEq (actualSlot, IMPLEMENTATION_SLOT);
254316 }
255317}
0 commit comments