diff --git a/test/WakuRlnV2.t.sol b/test/WakuRlnV2.t.sol index b73ba73..2116d50 100644 --- a/test/WakuRlnV2.t.sol +++ b/test/WakuRlnV2.t.sol @@ -1561,49 +1561,6 @@ contract WakuRlnV2Test is Test { w.setMaxTotalRateLimit(100); } - // Test: Malicious Upgrade Drains Funds - function test_MaliciousUpgradeDrainsFunds() external { - // Setup: Register with deposit - uint32 rateLimit = w.minMembershipRateLimit(); - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - token.approve(address(w), price); - w.register(1, rateLimit, new uint256[](0)); - - // Deploy malicious impl (e.g., drains token balance) - address maliciousImpl = address(new MaliciousImplementation()); // Assume impl with drain function - - // Prank owner to upgrade - vm.prank(w.owner()); - w.upgradeTo(address(maliciousImpl)); - - // Simulate drain (cast to malicious and call) - MaliciousImplementation malicious = MaliciousImplementation(address(w)); - vm.expectRevert(); // Or assert drain fails if protected - malicious.drainTokens(address(token)); - - // Assert: Funds not drained (invariant: no direct access) - assertEq(token.balanceOf(address(w)), price); // Still held - } - - // Test: Demonstrate success of Unauthorized Upgrade Post-Malicious Change - function test_UnauthorizedUpgradeAfterMalicious() external { - // Deploy malicious impl that allows anyone to upgrade - address maliciousImpl = address(new MaliciousImplementation()); // Overrides _authorizeUpgrade to public - - // Owner upgrades to malicious - vm.prank(w.owner()); - w.upgradeTo(address(maliciousImpl)); - - // Non-owner attempts further upgrade - address newImpl = address(new TestStableToken()); // Arbitrary - vm.prank(address(0xdead)); - w.upgradeTo(newImpl); // Should succeed if malicious allows, but test revert if protected - - // Assert: Bricked or unauthorized (depending on spec; expect revert for safety) - vm.expectRevert("Ownable: caller is not the owner"); - w.upgradeTo(newImpl); // If not overridden - } - // Helper: Verify Merkle Proof Manually function _verifyMerkleProof( uint256[20] memory proof, @@ -1752,91 +1709,4 @@ contract WakuRlnV2Test is Test { assertFalse(w.isExpired(1)); } } - - function testFrontrunning_RegistrationRevertsForVictim() external { - // Setup: Two users, Alice (victim) and Bob (attacker) - address alice = makeAddr("alice"); - address bob = makeAddr("bob"); - - // Mint and approve tokens for both (assuming min rate limit requires 1e18 tokens) - uint32 rateLimit = w.minMembershipRateLimit(); - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - vm.prank(address(tokenDeployer)); - token.mint(alice, price); - vm.prank(address(tokenDeployer)); - token.mint(bob, price); - - vm.prank(alice); - token.approve(address(w), price); - vm.prank(bob); - token.approve(address(w), price); - - // Alice's intended idCommitment - uint256 idCommitment = 123; // Arbitrary valid commitment (1 < id < Q) - - // Simulate frontrun: Prank Bob to register first with Alice's idCommitment - vm.prank(bob); - w.register(idCommitment, rateLimit, new uint256[](0)); - - // Now prank Alice: Her registration should succeed if no frontrun, but since it was frontrun, this will revert - // and fail the test - vm.prank(alice); - w.register(idCommitment, rateLimit, new uint256[](0)); - - // Assertions: If we reach here (no revert), check Alice owns it—but since revert happens, test fails - (uint32 fetchedRateLimit,,) = w.getMembershipInfo(idCommitment); - assertEq(fetchedRateLimit, rateLimit); - - // Destructure to access holder - (,,,,,, address holder,) = w.memberships(idCommitment); - assertEq(holder, alice); // This would fail if Bob sniped, but test already fails on revert - - assertFalse(w.isInMembershipSet(456)); // Arbitrary other ID for Alice not registered - } - - function testFrontrunning_SetFillingSpam() external { - // Prank owner to adjust limits for test - uint32 rateLimit = w.minMembershipRateLimit(); // Assume 20 - vm.prank(w.owner()); - w.setMaxMembershipRateLimit(rateLimit); // e.g., 20 - vm.prank(w.owner()); - w.setMaxTotalRateLimit(rateLimit * 2); // e.g., 40, for 2 memberships - - // Setup attacker and victim - address bob = makeAddr("bob"); // Attacker - address alice = makeAddr("alice"); // Victim - - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - - // Mint and approve for Bob and Alice - vm.prank(address(tokenDeployer)); - token.mint(bob, price * 2); // Enough for two registrations - vm.prank(address(tokenDeployer)); - token.mint(alice, price); - - vm.prank(bob); - token.approve(address(w), price * 2); - vm.prank(alice); - token.approve(address(w), price); - - // Bob registers one junk to make it almost full - uint256 junkId = 789; // Valid ID - vm.prank(bob); - w.register(junkId, rateLimit, new uint256[](0)); - - // Alice's intended idCommitment - uint256 aliceId = 123; - - // Frontrun: Bob snipes the last capacity with Alice's idCommitment - vm.prank(bob); - w.register(aliceId, rateLimit, new uint256[](0)); - - // Alice tries to register a different ID but capacity is exceeded (no expectRevert, so test fails on revert) - vm.prank(alice); - w.register(456, rateLimit, new uint256[](0)); // Different ID, but full capacity - - // Assertions: If no revert (which won't happen), check Alice owns it—but test fails earlier - (,,,,,, address holder,) = w.memberships(456); - assertEq(holder, alice); // This would fail if capacity exceeded, but revert happens first - } }