diff --git a/test/WakuRlnV2.t.sol b/test/WakuRlnV2.t.sol index cb16dc1..a951253 100644 --- a/test/WakuRlnV2.t.sol +++ b/test/WakuRlnV2.t.sol @@ -1538,153 +1538,4 @@ contract WakuRlnV2Test is Test { vm.expectRevert("Ownable: caller is not the owner"); w.setMaxTotalRateLimit(100); } - - // Helper: Verify Merkle Proof Manually - function _verifyMerkleProof( - uint256[20] memory proof, - uint256 root, - uint32 index, - uint256 leaf, - uint8 depth - ) - internal - pure - returns (bool) - { - uint256 current = leaf; - uint32 idx = index; - for (uint8 level = 0; level < depth; level++) { - bool isLeft = (idx & 1) == 0; - uint256 sibling = proof[level]; - uint256[2] memory inputs; - if (isLeft) { - inputs[0] = current; - inputs[1] = sibling; - } else { - inputs[0] = sibling; - inputs[1] = current; - } - current = PoseidonT3.hash(inputs); - idx >>= 1; - } - return current == root; - } - - function test_MultiUserEraseReuseRace(uint8 numUsers, bool fullErase) external { - vm.assume(numUsers > 1 && numUsers <= 8); - uint32 rateLimit = w.minMembershipRateLimit(); - - address tokenOwner = address(tokenDeployer); - - // Multi-user registers - for (uint8 i = 1; i <= numUsers; i++) { - address user = vm.addr(i); - - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - vm.prank(tokenOwner); - token.mint(user, price); - - vm.startPrank(user); - token.approve(address(w), price); - w.register(i, rateLimit, new uint256[](0)); - vm.stopPrank(); - } - - vm.warp(block.timestamp + w.activeDurationForNewMemberships() + w.gracePeriodDurationForNewMemberships() + 1); - - // Fuzz unique erasures - uint8 numErasures = uint8(uint256(keccak256(abi.encodePacked(block.timestamp))) % (numUsers / 2)) + 1; - uint256[] memory eraseIds = new uint256[](numErasures); - bool[] memory erased = new bool[](numUsers + 1); // Track to avoid duplicates - uint8 eraseCount = 0; - while (eraseCount < numErasures) { - uint8 eraseIdx = uint8(uint256(keccak256(abi.encodePacked(block.timestamp, eraseCount))) % numUsers) + 1; - if (!erased[eraseIdx]) { - eraseIds[eraseCount] = eraseIdx; - erased[eraseIdx] = true; - eraseCount++; - } - } - uint8 eraser = uint8(uint256(keccak256(abi.encodePacked(block.timestamp))) % numUsers) + 1; - vm.prank(vm.addr(eraser)); - w.eraseMemberships(eraseIds, fullErase); - - // Other users attempt reuses (balance to numErasures) - uint8 numReuses = numErasures; // Balance to no net growth - for (uint8 i = 0; i < numReuses; i++) { - uint8 reuser = uint8(uint256(keccak256(abi.encodePacked(block.timestamp, i + numUsers))) % numUsers) + 1; - address user = vm.addr(reuser); - - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - vm.prank(tokenOwner); - token.mint(user, price); - - vm.startPrank(user); - token.approve(address(w), price); - uint256 newId = - 100 + uint256(keccak256(abi.encodePacked("new", reuser, block.timestamp, i))) % (w.Q() - 1) + 1; - // uniqueness - w.register(newId, rateLimit, new uint256[](0)); - vm.stopPrank(); - } - - // Assert: No inconsistencies, reuses correct, proofs valid - for (uint8 i = 1; i <= numUsers; i++) { - bool isErased = erased[i]; - uint256 checkId = isErased ? 0 : i; - if (checkId != 0) { - (, uint32 idx, uint256 commitment) = w.getMembershipInfo(checkId); - uint256[20] memory proof = w.getMerkleProof(idx); - assertTrue(_verifyMerkleProof(proof, w.root(), idx, commitment, 20)); - } - } - assertEq(w.nextFreeIndex(), numUsers); // No growth beyond (reuses fill erased) - } - - function test_TimestampManipulationRaces(int16 deltaOffset) external { - vm.assume(deltaOffset >= -15 && deltaOffset <= 15); // Miner manipulation range - - uint32 rateLimit = w.minMembershipRateLimit(); - (, uint256 price) = w.priceCalculator().calculate(rateLimit); - token.approve(address(w), price); - w.register(1, rateLimit, new uint256[](0)); - - // Warp to near grace end (manipulable point) - uint256 graceEnd = - block.timestamp + w.activeDurationForNewMemberships() + w.gracePeriodDurationForNewMemberships(); - - // Compute absolute value - int256 delta = int256(deltaOffset); - int256 absDelta = delta >= 0 ? delta : -delta; - uint256 offsetAbs; - assembly { - offsetAbs := absDelta - } - - uint256 newTimestamp = delta >= 0 ? graceEnd + offsetAbs : graceEnd - offsetAbs; - vm.warp(newTimestamp); - - // Attempt extension (race: should fail if manipulated at the end) - uint256[] memory ids = new uint256[](1); - ids[0] = 1; - if (deltaOffset >= 0) { - // Manipulated at/after: expired (exclusive end) - vm.expectRevert(abi.encodeWithSelector(CannotExtendNonGracePeriodMembership.selector, ids[0])); - } - w.extendMemberships(ids); - - // Attempt erase (race: should succeed if at/after, fail if before) - if (deltaOffset < 0) { - // Manipulated before: not expired - vm.expectRevert(abi.encodeWithSelector(CannotEraseActiveMembership.selector, ids[0])); - } - w.eraseMemberships(ids, true); - - // Assert states based on manipulation - if (deltaOffset >= 0) { - assertTrue(w.isExpired(1)); - } else { - assertFalse(w.isExpired(1)); - } - } }