fix: remove test_MultiUserEraseReuseRace

- test_TimestampManipulationRaces
This commit is contained in:
Roman 2025-10-27 12:55:35 +08:00
parent 7c8d2d7b89
commit f8d670e41e
No known key found for this signature in database
GPG Key ID: 583BDF43C238B83E

View File

@ -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));
}
}
}