mirror of
https://github.com/logos-messaging/logos-messaging-rlnv2-contract.git
synced 2026-01-02 14:03:07 +00:00
chore: RLN contract unit test expansion 2 (#39)
* test: mass registration and erasure - warning cleanup * test: large pagination query * test: empty range pagination query * test: impact of duration changes * test: upgrade with invalid implementation * test: unauthorized merkle tree modifications * test: owner configuration updates * fix: update gas-snapshot
This commit is contained in:
parent
a1d97fcad9
commit
e75ac913e5
121
.gas-snapshot
121
.gas-snapshot
@ -1,51 +1,70 @@
|
||||
TestStableTokenTest:test__CannotAddAlreadyMinterRole() (gas: 46015)
|
||||
TestStableTokenTest:test__CannotRemoveNonMinterRole() (gas: 22633)
|
||||
TestStableTokenTest:test__CheckMinterRoleMapping() (gas: 69942)
|
||||
TestStableTokenTest:test__ERC20BasicFunctionality() (gas: 128100)
|
||||
TestStableTokenTest:test__MinterAddedEventEmitted() (gas: 44860)
|
||||
TestStableTokenTest:test__MinterRemovedEventEmitted() (gas: 34564)
|
||||
TestStableTokenTest:test__MinterRoleCanMint() (gas: 95547)
|
||||
TestStableTokenTest:test__MultipleMinterRolesCanMint() (gas: 125690)
|
||||
TestStableTokenTest:test__NonMinterNonOwnerAccountCannotMint() (gas: 22562)
|
||||
TestStableTokenTest:test__NonOwnerCannotAddMinterRole() (gas: 18154)
|
||||
TestStableTokenTest:test__NonOwnerCannotRemoveMinterRole() (gas: 45632)
|
||||
TestStableTokenTest:test__OwnerCanAddMinterRole() (gas: 47069)
|
||||
TestStableTokenTest:test__OwnerCanAlwaysMintEvenWithoutMinterRole() (gas: 71856)
|
||||
TestStableTokenTest:test__OwnerCanMintWithoutMinterRole() (gas: 67951)
|
||||
TestStableTokenTest:test__OwnerCanRemoveMinterRole() (gas: 36328)
|
||||
TestStableTokenTest:test__RemovedMinterRoleCannotMint() (gas: 37100)
|
||||
WakuRlnV2Test:test__ErasingNonExistentMembership() (gas: 46033)
|
||||
WakuRlnV2Test:test__FullCleanUpErasure() (gas: 1016600)
|
||||
WakuRlnV2Test:test__GracePeriodExtensionEdgeCases() (gas: 327838)
|
||||
WakuRlnV2Test:test__IdCommitmentToMetadata__DoesntExist() (gas: 25380)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__EndIndexGTNextFreeIndex() (gas: 18365)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__StartIndexGTEndIndex() (gas: 16235)
|
||||
WakuRlnV2Test:test__InvalidRegistration__DuplicateIdCommitment() (gas: 305899)
|
||||
WakuRlnV2Test:test__InvalidRegistration__FullTree() (gas: 56414)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__LargerThanField() (gas: 43985)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__Zero() (gas: 42716)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidMembershipRateLimit__MinMax() (gas: 55485)
|
||||
WakuRlnV2Test:test__InvalidTokenAmount(uint256,uint32) (runs: 1000, μ: 191559, ~: 191559)
|
||||
WakuRlnV2Test:test__LinearPriceCalculation(uint32) (runs: 1000, μ: 26091, ~: 26091)
|
||||
WakuRlnV2Test:test__MaxTotalRateLimitEdgeCases() (gas: 21815151)
|
||||
WakuRlnV2Test:test__MerkleTreeUpdateAfterErasureAndReuse() (gas: 2426423)
|
||||
WakuRlnV2Test:test__PriceCalculatorReconfiguration() (gas: 669694)
|
||||
WakuRlnV2Test:test__RegistrationWhenMaxRateLimitIsReached() (gas: 594536)
|
||||
WakuRlnV2Test:test__ReinitializationProtection() (gas: 79848)
|
||||
WakuRlnV2Test:test__RemoveAllExpiredMemberships(uint32) (runs: 1000, μ: 5031235, ~: 2443747)
|
||||
WakuRlnV2Test:test__RemoveExpiredMemberships(uint32) (runs: 1000, μ: 1146012, ~: 1146012)
|
||||
WakuRlnV2Test:test__TokenTransferFailures() (gas: 4092129)
|
||||
WakuRlnV2Test:test__Upgrade() (gas: 6702686)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery(uint32) (runs: 1000, μ: 385132, ~: 134408)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 301131)
|
||||
WakuRlnV2Test:test__ValidRegistration(uint32) (runs: 1000, μ: 307480, ~: 307480)
|
||||
WakuRlnV2Test:test__ValidRegistrationExpiry(uint32) (runs: 1000, μ: 288428, ~: 288428)
|
||||
WakuRlnV2Test:test__ValidRegistrationExtend(uint32) (runs: 1000, μ: 534572, ~: 534572)
|
||||
WakuRlnV2Test:test__ValidRegistrationExtendSingleMembership(uint32) (runs: 1000, μ: 296089, ~: 296089)
|
||||
WakuRlnV2Test:test__ValidRegistrationNoGracePeriod(uint32) (runs: 1000, μ: 292083, ~: 292083)
|
||||
WakuRlnV2Test:test__ValidRegistrationWithEraseList() (gas: 1302532)
|
||||
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 277468)
|
||||
WakuRlnV2Test:test__WithdrawToken(uint32) (runs: 1000, μ: 277715, ~: 277715)
|
||||
WakuRlnV2Test:test__ZeroGracePeriodDuration() (gas: 8156213)
|
||||
WakuRlnV2Test:test__ZeroPriceEdgeCase() (gas: 791477)
|
||||
WakuRlnV2Test:test__indexReuse_eraseMemberships(uint32) (runs: 1000, μ: 4230350, ~: 1420233)
|
||||
TestStableTokenTest:test__CannotAddAlreadyMinterRole() (gas: 46286)
|
||||
TestStableTokenTest:test__CannotMintExceedingMaxSupply() (gas: 26202)
|
||||
TestStableTokenTest:test__CannotMintWithETHExceedingMaxSupply() (gas: 31164)
|
||||
TestStableTokenTest:test__CannotMintWithZeroETH() (gas: 18282)
|
||||
TestStableTokenTest:test__CannotRemoveNonMinterRole() (gas: 22638)
|
||||
TestStableTokenTest:test__CannotSetMaxSupplyBelowTotalSupply() (gas: 71114)
|
||||
TestStableTokenTest:test__CheckMinterRoleMapping() (gas: 70651)
|
||||
TestStableTokenTest:test__ContractDoesNotHoldETHAfterMint() (gas: 110700)
|
||||
TestStableTokenTest:test__ERC20BasicFunctionality() (gas: 146240)
|
||||
TestStableTokenTest:test__ETHBurnedEventEmitted() (gas: 112584)
|
||||
TestStableTokenTest:test__ETHIsBurnedToZeroAddress() (gas: 110545)
|
||||
TestStableTokenTest:test__MaxSupplyIsSetCorrectly() (gas: 15409)
|
||||
TestStableTokenTest:test__MintRequiresETH() (gas: 18254)
|
||||
TestStableTokenTest:test__MintWithDifferentETHAmounts() (gas: 209672)
|
||||
TestStableTokenTest:test__MinterAddedEventEmitted() (gas: 44991)
|
||||
TestStableTokenTest:test__MinterRemovedEventEmitted() (gas: 34697)
|
||||
TestStableTokenTest:test__MinterRoleCanMint() (gas: 98026)
|
||||
TestStableTokenTest:test__MultipleMinterRolesCanMint() (gas: 128734)
|
||||
TestStableTokenTest:test__NonMinterNonOwnerAccountCannotMint() (gas: 22444)
|
||||
TestStableTokenTest:test__NonOwnerCannotAddMinterRole() (gas: 18239)
|
||||
TestStableTokenTest:test__NonOwnerCannotRemoveMinterRole() (gas: 45775)
|
||||
TestStableTokenTest:test__NonOwnerCannotSetMaxSupply() (gas: 18070)
|
||||
TestStableTokenTest:test__OwnerCanAddMinterRole() (gas: 47336)
|
||||
TestStableTokenTest:test__OwnerCanMintWithoutMinterRole() (gas: 74316)
|
||||
TestStableTokenTest:test__OwnerCanRemoveMinterRole() (gas: 36544)
|
||||
TestStableTokenTest:test__OwnerCanSetMaxSupply() (gas: 30683)
|
||||
TestStableTokenTest:test__RemovedMinterRoleCannotMint() (gas: 37086)
|
||||
WakuRlnV2Test:test__EmptyRangePagination() (gas: 307693)
|
||||
WakuRlnV2Test:test__ErasingNonExistentMembership() (gas: 46131)
|
||||
WakuRlnV2Test:test__FullCleanUpErasure() (gas: 1016790)
|
||||
WakuRlnV2Test:test__GracePeriodExtensionEdgeCases() (gas: 328094)
|
||||
WakuRlnV2Test:test__IdCommitmentToMetadata__DoesntExist() (gas: 25425)
|
||||
WakuRlnV2Test:test__ImpactOfDurationChangesOnExistingMemberships() (gas: 540089)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__EndIndexGTNextFreeIndex() (gas: 18353)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__StartIndexGTEndIndex() (gas: 16223)
|
||||
WakuRlnV2Test:test__InvalidRegistration__DuplicateIdCommitment() (gas: 306169)
|
||||
WakuRlnV2Test:test__InvalidRegistration__FullTree() (gas: 56506)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__LargerThanField() (gas: 44077)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__Zero() (gas: 42830)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidMembershipRateLimit__MinMax() (gas: 55598)
|
||||
WakuRlnV2Test:test__InvalidTokenAmount(uint256,uint32) (runs: 1000, μ: 191620, ~: 191620)
|
||||
WakuRlnV2Test:test__LargePaginationQuery() (gas: 237941853)
|
||||
WakuRlnV2Test:test__LinearPriceCalculation(uint32) (runs: 1000, μ: 26069, ~: 26069)
|
||||
WakuRlnV2Test:test__MassRegistrationAndErasure() (gas: 2714587)
|
||||
WakuRlnV2Test:test__MaxTotalRateLimitEdgeCases() (gas: 21832122)
|
||||
WakuRlnV2Test:test__MerkleTreeUpdateAfterErasureAndReuse() (gas: 2426716)
|
||||
WakuRlnV2Test:test__NonMinterCanMintWithETHAndRegister() (gas: 373178)
|
||||
WakuRlnV2Test:test__OwnerConfigurationUpdates() (gas: 53177)
|
||||
WakuRlnV2Test:test__PriceCalculatorReconfiguration() (gas: 669789)
|
||||
WakuRlnV2Test:test__RegistrationWhenMaxRateLimitIsReached() (gas: 595140)
|
||||
WakuRlnV2Test:test__ReinitializationProtection() (gas: 80197)
|
||||
WakuRlnV2Test:test__RemoveAllExpiredMemberships(uint32) (runs: 1000, μ: 5020828, ~: 2445573)
|
||||
WakuRlnV2Test:test__RemoveExpiredMemberships(uint32) (runs: 1000, μ: 1146896, ~: 1146896)
|
||||
WakuRlnV2Test:test__TokenTransferFailures() (gas: 4114224)
|
||||
WakuRlnV2Test:test__UnauthorizedMerkleTreeModifications() (gas: 1113852)
|
||||
WakuRlnV2Test:test__Upgrade() (gas: 6702671)
|
||||
WakuRlnV2Test:test__UpgradeWithInvalidImplementation() (gas: 51496)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery(uint32) (runs: 1000, μ: 393970, ~: 134452)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 301276)
|
||||
WakuRlnV2Test:test__ValidRegistration(uint32) (runs: 1000, μ: 307585, ~: 307585)
|
||||
WakuRlnV2Test:test__ValidRegistrationExpiry(uint32) (runs: 1000, μ: 288640, ~: 288640)
|
||||
WakuRlnV2Test:test__ValidRegistrationExtend(uint32) (runs: 1000, μ: 534996, ~: 534996)
|
||||
WakuRlnV2Test:test__ValidRegistrationExtendSingleMembership(uint32) (runs: 1000, μ: 296279, ~: 296279)
|
||||
WakuRlnV2Test:test__ValidRegistrationNoGracePeriod(uint32) (runs: 1000, μ: 292251, ~: 292251)
|
||||
WakuRlnV2Test:test__ValidRegistrationWithEraseList() (gas: 1303567)
|
||||
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 277614)
|
||||
WakuRlnV2Test:test__WithdrawToken(uint32) (runs: 1000, μ: 277708, ~: 277708)
|
||||
WakuRlnV2Test:test__ZeroGracePeriodDuration() (gas: 8156320)
|
||||
WakuRlnV2Test:test__ZeroPriceEdgeCase() (gas: 791578)
|
||||
WakuRlnV2Test:test__indexReuse_eraseMemberships(uint32) (runs: 1000, μ: 4235383, ~: 1628509)
|
||||
@ -278,7 +278,7 @@ contract TestStableTokenTest is Test {
|
||||
token.mintWithETH{ value: 0 }(user2);
|
||||
}
|
||||
|
||||
function test__MaxSupplyIsSetCorrectly() external {
|
||||
function test__MaxSupplyIsSetCorrectly() external view {
|
||||
// maxSupply should be set to 1000000 * 10^18 by deployment script
|
||||
uint256 expectedMaxSupply = 1_000_000 * 10 ** 18;
|
||||
assertEq(token.maxSupply(), expectedMaxSupply);
|
||||
|
||||
@ -63,6 +63,10 @@ contract MockPriceCalculator is IPriceCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
contract NonUUPSContract {
|
||||
// A mock contract that does not support UUPS (no proxiable UUID or _authorizeUpgrade)
|
||||
}
|
||||
|
||||
contract WakuRlnV2Test is Test {
|
||||
WakuRlnV2 internal w;
|
||||
TestStableToken internal token;
|
||||
@ -693,7 +697,6 @@ contract WakuRlnV2Test is Test {
|
||||
|
||||
// Calculate required token amount for membership
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
uint256 ethAmount = price; // Use same amount of ETH as token price needed
|
||||
|
||||
// Verify nonMinter is not a minter
|
||||
assertFalse(token.isMinter(nonMinter));
|
||||
@ -1302,4 +1305,241 @@ contract WakuRlnV2Test is Test {
|
||||
); // expected root after insert
|
||||
assertEq(token.balanceOf(address(w)), 0); // No transfer
|
||||
}
|
||||
|
||||
function test__MassRegistrationAndErasure() external {
|
||||
uint32 num = 10; // Number of memberships to register - adjust for gas limits in testing
|
||||
uint32 rateLimit = 1; // Low to fit max total
|
||||
vm.prank(w.owner());
|
||||
w.setMinMembershipRateLimit(1);
|
||||
|
||||
vm.prank(w.owner());
|
||||
w.setMaxMembershipRateLimit(1);
|
||||
|
||||
vm.prank(w.owner());
|
||||
w.setMaxTotalRateLimit(num * rateLimit);
|
||||
|
||||
vm.prank(w.owner());
|
||||
w.setActiveDuration(600); // 10 minutes
|
||||
|
||||
vm.prank(w.owner());
|
||||
w.setGracePeriodDuration(240); // 4 minutes
|
||||
|
||||
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
|
||||
|
||||
for (uint256 i = 1; i <= num; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(i, rateLimit, noIdCommitmentsToErase);
|
||||
}
|
||||
assertEq(w.nextFreeIndex(), num);
|
||||
assertEq(w.currentTotalRateLimit(), num * rateLimit);
|
||||
|
||||
// Warp to expire all
|
||||
vm.warp(
|
||||
block.timestamp + uint256(w.activeDurationForNewMemberships())
|
||||
+ uint256(w.gracePeriodDurationForNewMemberships()) + 1
|
||||
);
|
||||
|
||||
uint256[] memory toErase = new uint256[](num / 2);
|
||||
for (uint256 i = 0; i < num / 2; i++) {
|
||||
toErase[i] = i + 1;
|
||||
}
|
||||
w.eraseMemberships(toErase, false); // Lazy half
|
||||
|
||||
uint256[] memory toEraseFull = new uint256[](num / 2);
|
||||
for (uint256 i = num / 2; i < num; i++) {
|
||||
toEraseFull[i - num / 2] = i + 1;
|
||||
}
|
||||
w.eraseMemberships(toEraseFull, true); // Full half
|
||||
|
||||
assertEq(w.currentTotalRateLimit(), 0);
|
||||
|
||||
// Verify root and commitments
|
||||
uint256[] memory actual_rcs = w.getRateCommitmentsInRangeBoundsInclusive(0, num - 1);
|
||||
uint256[] memory expected_rcs = new uint256[](num);
|
||||
for (uint256 i = 0; i < num; i++) {
|
||||
if (i < num / 2) {
|
||||
// Lazy erased: commitments remain as original
|
||||
expected_rcs[i] = PoseidonT3.hash([uint256(i + 1), uint256(rateLimit)]);
|
||||
} else {
|
||||
// Fully erased: commitments set to 0
|
||||
expected_rcs[i] = 0;
|
||||
}
|
||||
assertEq(actual_rcs[i], expected_rcs[i]);
|
||||
}
|
||||
|
||||
// Verify all memberships are considered erased (rateLimit == 0)
|
||||
for (uint256 i = 1; i <= num; i++) {
|
||||
(uint32 rl, uint32 idx, uint256 rc) = w.getMembershipInfo(i);
|
||||
assertEq(rl, 0);
|
||||
assertEq(idx, 0);
|
||||
assertEq(rc, 0);
|
||||
assertFalse(w.isInMembershipSet(i));
|
||||
}
|
||||
|
||||
// Optionally, verify the Merkle root is non-zero (since partial tree remains)
|
||||
assertNotEq(w.root(), 0);
|
||||
}
|
||||
|
||||
function test__LargePaginationQuery() external {
|
||||
uint32 num = 1000;
|
||||
uint32 rateLimit = w.minMembershipRateLimit();
|
||||
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
|
||||
|
||||
// Register 'num' memberships
|
||||
for (uint256 i = 1; i <= num; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(i, rateLimit, noIdCommitmentsToErase);
|
||||
}
|
||||
|
||||
// Large query for the rate commitments
|
||||
uint256[] memory commitments = w.getRateCommitmentsInRangeBoundsInclusive(0, num - 1);
|
||||
assertEq(commitments.length, num);
|
||||
|
||||
// Verify each returned commitment matches the expected Poseidon hash
|
||||
for (uint256 i = 0; i < num; i++) {
|
||||
uint256 expected = PoseidonT3.hash([i + 1, rateLimit]);
|
||||
assertEq(commitments[i], expected);
|
||||
}
|
||||
}
|
||||
|
||||
function test__EmptyRangePagination() external {
|
||||
// Valid range with one element
|
||||
uint32 rateLimit = w.minMembershipRateLimit();
|
||||
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
|
||||
token.approve(address(w), price);
|
||||
w.register(1, rateLimit, noIdCommitmentsToErase);
|
||||
|
||||
uint256[] memory commitments = w.getRateCommitmentsInRangeBoundsInclusive(0, 0);
|
||||
assertEq(commitments.length, 1);
|
||||
|
||||
// Beyond nextFreeIndex
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidPaginationQuery.selector, 1, 1));
|
||||
w.getRateCommitmentsInRangeBoundsInclusive(1, 1);
|
||||
}
|
||||
|
||||
function test__ImpactOfDurationChangesOnExistingMemberships() external {
|
||||
uint32 originalActive = w.activeDurationForNewMemberships();
|
||||
uint32 originalGrace = w.gracePeriodDurationForNewMemberships();
|
||||
|
||||
uint32 rateLimit = w.minMembershipRateLimit();
|
||||
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(1, rateLimit, noIdCommitmentsToErase);
|
||||
|
||||
{
|
||||
(, uint32 active1,, uint32 grace1,,,,) = w.memberships(1);
|
||||
assertEq(active1, originalActive);
|
||||
assertEq(grace1, originalGrace);
|
||||
}
|
||||
|
||||
vm.prank(w.owner());
|
||||
w.setActiveDuration(20 minutes);
|
||||
vm.prank(w.owner());
|
||||
w.setGracePeriodDuration(5 minutes);
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(2, rateLimit, noIdCommitmentsToErase);
|
||||
|
||||
// Existing unchanged
|
||||
{
|
||||
(, uint32 active1,, uint32 grace1,,,,) = w.memberships(1);
|
||||
assertEq(active1, originalActive);
|
||||
assertEq(grace1, originalGrace);
|
||||
}
|
||||
|
||||
// New uses updated
|
||||
{
|
||||
(, uint32 active2,, uint32 grace2,,,,) = w.memberships(2);
|
||||
assertEq(active2, 20 minutes);
|
||||
assertEq(grace2, 5 minutes);
|
||||
}
|
||||
}
|
||||
|
||||
function test__UpgradeWithInvalidImplementation() external {
|
||||
// Deploy an invalid (non-UUPS) implementation contract
|
||||
address invalidImpl = address(new NonUUPSContract());
|
||||
|
||||
// Capture the current implementation address from the ERC1967 slot
|
||||
bytes32 implSlot = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
|
||||
address originalImpl = address(uint160(uint256(vm.load(address(w), implSlot))));
|
||||
|
||||
// Impersonate the owner and expect the specific UUPS revert for unsupported proxiable UUID
|
||||
vm.prank(w.owner());
|
||||
vm.expectRevert("ERC1967Upgrade: new implementation is not UUPS");
|
||||
UUPSUpgradeable(address(w)).upgradeTo(invalidImpl);
|
||||
|
||||
// Verify the implementation slot remains unchanged (still the original)
|
||||
address currentImpl = address(uint160(uint256(vm.load(address(w), implSlot))));
|
||||
assertEq(currentImpl, originalImpl);
|
||||
assertNotEq(currentImpl, invalidImpl);
|
||||
}
|
||||
|
||||
function test__UnauthorizedMerkleTreeModifications() external {
|
||||
// Register a single membership to populate the Merkle tree
|
||||
uint32 rateLimit = w.minMembershipRateLimit();
|
||||
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
|
||||
token.approve(address(w), price);
|
||||
w.register(1, rateLimit, noIdCommitmentsToErase);
|
||||
|
||||
// Capture the initial Merkle tree root
|
||||
uint256 initialRoot = w.root();
|
||||
|
||||
// Attempt a low-level call to a nonexistent public function resembling LazyIMT's internal update
|
||||
// Since LazyIMT's update is internal, no such function exists publicly, so the call will fail
|
||||
bytes memory invalidCallData = abi.encodeWithSignature("update(uint256,uint32)", 0, 0);
|
||||
(bool success,) = address(w).call(invalidCallData);
|
||||
|
||||
// Verify the call failed (no public function exists)
|
||||
assertFalse(success);
|
||||
|
||||
// Verify the Merkle tree root remains unchanged
|
||||
assertEq(w.root(), initialRoot);
|
||||
|
||||
// Verify membership data is intact
|
||||
(uint32 fetchedRateLimit, uint32 index, uint256 rateCommitment) = w.getMembershipInfo(1);
|
||||
assertEq(fetchedRateLimit, rateLimit);
|
||||
assertEq(index, 0);
|
||||
assertEq(rateCommitment, PoseidonT3.hash([uint256(1), uint256(rateLimit)]));
|
||||
}
|
||||
|
||||
function test__OwnerConfigurationUpdates() external {
|
||||
address owner = w.owner();
|
||||
vm.startPrank(owner);
|
||||
|
||||
// Ensure maxMembershipRateLimit is compatible with maxTotalRateLimit
|
||||
w.setMaxMembershipRateLimit(100);
|
||||
assertEq(w.maxMembershipRateLimit(), 100);
|
||||
|
||||
// Set minMembershipRateLimit first to allow maxMembershipRateLimit=15
|
||||
w.setMinMembershipRateLimit(2);
|
||||
assertEq(w.minMembershipRateLimit(), 2);
|
||||
|
||||
// Valid updates
|
||||
w.setMaxTotalRateLimit(200);
|
||||
assertEq(w.maxTotalRateLimit(), 200);
|
||||
|
||||
w.setMaxMembershipRateLimit(15);
|
||||
assertEq(w.maxMembershipRateLimit(), 15);
|
||||
|
||||
w.setActiveDuration(20 minutes);
|
||||
assertEq(w.activeDurationForNewMemberships(), 20 minutes);
|
||||
|
||||
w.setGracePeriodDuration(5 minutes);
|
||||
assertEq(w.gracePeriodDurationForNewMemberships(), 5 minutes);
|
||||
|
||||
// Invalid updates
|
||||
vm.expectRevert(); // Generic revert for require(_minMembershipRateLimit <= maxMembershipRateLimit)
|
||||
w.setMinMembershipRateLimit(20);
|
||||
|
||||
vm.expectRevert(); // Generic revert for require(_activeDurationForNewMembership > 0)
|
||||
w.setActiveDuration(0);
|
||||
|
||||
vm.stopPrank();
|
||||
|
||||
// Non-owner
|
||||
vm.prank(vm.addr(1));
|
||||
vm.expectRevert("Ownable: caller is not the owner");
|
||||
w.setMaxTotalRateLimit(100);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user