Merge branch 'main' into feat/expand-root-storage-window to include updated tests

This commit is contained in:
stubbsta 2025-11-17 12:04:31 +02:00
commit 1fd8247640
No known key found for this signature in database
10 changed files with 420 additions and 58 deletions

View File

@ -1,30 +1,33 @@
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)
TestStableTokenTest:test__CannotAddAlreadyMinterRole() (gas: 46248)
TestStableTokenTest:test__CannotMintExceedingMaxSupply() (gas: 26253)
TestStableTokenTest:test__CannotMintWithETHExceedingMaxSupply() (gas: 31196)
TestStableTokenTest:test__CannotMintWithZeroETH() (gas: 18269)
TestStableTokenTest:test__CannotRemoveNonMinterRole() (gas: 22686)
TestStableTokenTest:test__CannotSetMaxSupplyBelowTotalSupply() (gas: 71121)
TestStableTokenTest:test__CheckMinterRoleMapping() (gas: 70476)
TestStableTokenTest:test__ContractDoesNotHoldETHAfterMint() (gas: 110659)
TestStableTokenTest:test__ERC20BasicFunctionality() (gas: 146438)
TestStableTokenTest:test__ETHBurnedEventEmitted() (gas: 112577)
TestStableTokenTest:test__ETHIsBurnedToZeroAddress() (gas: 110526)
TestStableTokenTest:test__InitializeZeroReverts() (gas: 2558591)
TestStableTokenTest:test__MaxSupplyIsSetCorrectly() (gas: 15454)
TestStableTokenTest:test__MintRequiresETH() (gas: 18285)
TestStableTokenTest:test__MintWithDifferentETHAmounts() (gas: 209788)
TestStableTokenTest:test__MintWithETH_RevertsBelowOneETH() (gas: 25455)
TestStableTokenTest:test__MintWithETH_SucceedsAtOneETH() (gas: 110063)
TestStableTokenTest:test__MinterAddedEventEmitted() (gas: 44947)
TestStableTokenTest:test__MinterRemovedEventEmitted() (gas: 34662)
TestStableTokenTest:test__MinterRoleCanMint() (gas: 98092)
TestStableTokenTest:test__MultipleMinterRolesCanMint() (gas: 128755)
TestStableTokenTest:test__NonMinterNonOwnerAccountCannotMint() (gas: 22493)
TestStableTokenTest:test__NonOwnerCannotAddMinterRole() (gas: 18223)
TestStableTokenTest:test__NonOwnerCannotRemoveMinterRole() (gas: 45737)
TestStableTokenTest:test__NonOwnerCannotSetMaxSupply() (gas: 18054)
TestStableTokenTest:test__OwnerCanAddMinterRole() (gas: 47248)
TestStableTokenTest:test__OwnerCanMintWithoutMinterRole() (gas: 74382)
TestStableTokenTest:test__OwnerCanRemoveMinterRole() (gas: 36473)
TestStableTokenTest:test__OwnerCanSetMaxSupply() (gas: 30795)
TestStableTokenTest:test__RemovedMinterRoleCannotMint() (gas: 37073)
WakuRlnV2Test:test__EmptyRangePagination() (gas: 307693)
WakuRlnV2Test:test__ErasingNonExistentMembership() (gas: 46131)
WakuRlnV2Test:test__FullCleanUpErasure() (gas: 1016790)
@ -44,27 +47,27 @@ WakuRlnV2Test:test__LinearPriceCalculation(uint32) (runs: 1000, μ: 26069, ~: 26
WakuRlnV2Test:test__MassRegistrationAndErasure() (gas: 2714587)
WakuRlnV2Test:test__MaxTotalRateLimitEdgeCases() (gas: 21832122)
WakuRlnV2Test:test__MerkleTreeUpdateAfterErasureAndReuse() (gas: 2426716)
WakuRlnV2Test:test__NonMinterCanMintWithETHAndRegister() (gas: 373178)
WakuRlnV2Test:test__NonMinterCanMintWithETHAndRegister() (gas: 373332)
WakuRlnV2Test:test__OwnerConfigurationUpdates() (gas: 53177)
WakuRlnV2Test:test__PriceCalculatorReconfiguration() (gas: 669789)
WakuRlnV2Test:test__PriceCalculatorReconfiguration() (gas: 669854)
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__RemoveAllExpiredMemberships(uint32) (runs: 1000, μ: 4516570, ~: 2259520)
WakuRlnV2Test:test__RemoveExpiredMemberships(uint32) (runs: 1000, μ: 1055797, ~: 1055798)
WakuRlnV2Test:test__TokenTransferFailures() (gas: 4139092)
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(uint32) (runs: 1000, μ: 378536, ~: 134452)
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 301276)
WakuRlnV2Test:test__ValidRegistration(uint32) (runs: 1000, μ: 307585, ~: 307585)
WakuRlnV2Test:test__ValidRegistration(uint32) (runs: 1000, μ: 307650, ~: 307650)
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__ValidRegistrationWithEraseList() (gas: 1337020)
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 277614)
WakuRlnV2Test:test__WithdrawToken(uint32) (runs: 1000, μ: 277708, ~: 277708)
WakuRlnV2Test:test__WithdrawToken(uint32) (runs: 1000, μ: 283285, ~: 283286)
WakuRlnV2Test:test__ZeroGracePeriodDuration() (gas: 8156320)
WakuRlnV2Test:test__ZeroPriceEdgeCase() (gas: 791578)
WakuRlnV2Test:test__indexReuse_eraseMemberships(uint32) (runs: 1000, μ: 4235383, ~: 1628509)
WakuRlnV2Test:test__ZeroPriceEdgeCase() (gas: 791643)
WakuRlnV2Test:test__indexReuse_eraseMemberships(uint32) (runs: 1000, μ: 4269053, ~: 1835792)

View File

@ -117,7 +117,7 @@ jobs:
)" >> $GITHUB_ENV
- name: "Run the tests"
run: "forge test"
run: 'forge test --no-match-path "test/Echidna*.t.sol"'
- name: "Add test summary"
run: |
@ -151,7 +151,7 @@ jobs:
run: "pnpm install"
- name: "Generate the coverage report using the unit and the integration tests"
run: 'forge coverage --match-path "test/**/*.sol" --report lcov'
run: 'forge coverage --match-path "test/**/*.sol" --no-match-path "test/Echidna*.t.sol" --report lcov'
- name: "Upload coverage report to Codecov"
uses: "codecov/codecov-action@v3"

19
echidna.config.yaml Normal file
View File

@ -0,0 +1,19 @@
solcArgs: "--via-ir --optimize --optimize-runs 1"
testMode: property
testLimit: 100000 # For ~1 hour on strong CPU; adjust
seqLen: 100 # Sequence length for stateful fuzzing
shrinkLimit: 5000
corpusDir: corpus
deployContracts:
- ["0x0000000000000000000000000000000000001000", "PoseidonT3"]
- ["0x0000000000000000000000000000000000001001", "LazyIMT"]
cryticArgs:
- "--compile-libraries=(PoseidonT3,0x0000000000000000000000000000000000001000),(LazyIMT,0x0000000000000000000000000000000000001001)"
propMaxGas: 25000000
testMaxGas: 25000000
maxTimeDelay: 20000000 # ~231 days in seconds; set high to cover active (180 days / 15552000s) and grace (30 days / 2592000s) periods for expiration races
sender: ["0x10000", "0x20000", "0x30000", "0x40000"] # Multiple senders to simulate different users; expand if needed
balanceAddr: 100000000000000000000
coverage: true
quiet: false
projectName: "WakuRlnV2"

5
echidna_cleanup.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
rm -rf corpus
rm -f covered*.txt
rm -rf .crytic/
echo "Echidna artifacts cleaned up."

19
echidna_races.config.yaml Normal file
View File

@ -0,0 +1,19 @@
solcArgs: "--via-ir --optimize --optimize-runs 1"
testMode: assertion
testLimit: 100000 # For ~1 hour on strong CPU; adjust
seqLen: 100 # Sequence length for stateful fuzzing
shrinkLimit: 5000
corpusDir: corpus
deployContracts:
- ["0x0000000000000000000000000000000000001000", "PoseidonT3"]
- ["0x0000000000000000000000000000000000001001", "LazyIMT"]
cryticArgs:
- "--compile-libraries=(PoseidonT3,0x0000000000000000000000000000000000001000),(LazyIMT,0x0000000000000000000000000000000000001001)"
propMaxGas: 25000000
testMaxGas: 25000000
maxTimeDelay: 20000000 # ~231 days in seconds; set high to cover active (180 days / 15552000s) and grace (30 days / 2592000s) periods for expiration races
sender: ["0x10000", "0x20000", "0x30000", "0x40000"] # Multiple senders to simulate different users; expand if needed
balanceAddr: 100000000000000000000
coverage: true
quiet: false
projectName: "WakuRlnV2"

3
run_echidna_tests.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
echidna test/EchidnaTest.t.sol --contract EchidnaTest --config echidna.config.yaml
echidna test/EchidnaTestRaces.t.sol --contract EchidnaTestRaces --config echidna_races.config.yaml

171
test/EchidnaTest.t.sol Normal file
View File

@ -0,0 +1,171 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "../src/WakuRlnV2.sol";
import "../src/LinearPriceCalculator.sol";
import "../src/Membership.sol";
import "../test/TestStableToken.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract EchidnaTest {
WakuRlnV2 public w;
TestStableToken public token;
LinearPriceCalculator public priceCalculator;
uint32 public constant MAX_TOTAL_RATELIMIT_PER_EPOCH = 160_000;
uint32 public constant MIN_RATELIMIT_PER_MEMBERSHIP = 20;
uint32 public constant MAX_RATELIMIT_PER_MEMBERSHIP = 600;
uint32 public constant ACTIVE_DURATION = 180 days;
uint32 public constant GRACE_PERIOD_DURATION = 30 days;
uint256 public constant MAX_SUPPLY = 1_000_000 * 10 ** 18;
uint256[] public activeIdCommitments;
mapping(uint32 => uint256) public indexToId;
mapping(uint32 => uint32) public indexToRate;
mapping(uint256 => uint32) public idToExpectedActiveDuration;
constructor() {
// Deploy TestStableToken via proxy
address tokenImpl = address(new TestStableToken());
bytes memory tokenInitData = abi.encodeCall(TestStableToken.initialize, (MAX_SUPPLY));
ERC1967Proxy tokenProxy = new ERC1967Proxy(tokenImpl, tokenInitData);
token = TestStableToken(address(tokenProxy));
// Deploy LinearPriceCalculator
priceCalculator = new LinearPriceCalculator(address(token), 0.05 ether);
// Deploy WakuRlnV2 via proxy
address wImpl = address(new WakuRlnV2());
bytes memory wInitData = abi.encodeCall(
WakuRlnV2.initialize,
(
address(priceCalculator),
MAX_TOTAL_RATELIMIT_PER_EPOCH,
MIN_RATELIMIT_PER_MEMBERSHIP,
MAX_RATELIMIT_PER_MEMBERSHIP,
ACTIVE_DURATION,
GRACE_PERIOD_DURATION
)
);
ERC1967Proxy wProxy = new ERC1967Proxy(wImpl, wInitData);
w = WakuRlnV2(address(wProxy));
// Mint and approve tokens
token.mint(address(this), 1_000_000 ether);
token.approve(address(w), type(uint256).max);
}
// Helper for proof verification
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;
}
// Invariants
function echidna_rate_commitments_range_correct() public view returns (bool) {
uint32 nextFree = w.nextFreeIndex();
if (nextFree == 0) return true;
uint32 startIndex = 0;
uint32 endIndex = nextFree - 1;
uint256[] memory commitments = w.getRateCommitmentsInRangeBoundsInclusive(startIndex, endIndex);
if (commitments.length != uint256(endIndex - startIndex + 1)) {
return false;
}
for (uint32 j = startIndex; j <= endIndex; j++) {
if (indexToRate[j] != 0) {
uint256 exp = PoseidonT3.hash([indexToId[j], uint256(indexToRate[j])]);
if (commitments[j - startIndex] != exp) {
return false;
}
}
}
return true;
}
function echidna_merkle_proof_valid() public view returns (bool) {
uint32 nextFree = w.nextFreeIndex();
if (nextFree == 0) return true;
for (uint32 index = 0; index < nextFree; index++) {
uint256[20] memory proof = w.getMerkleProof(index);
uint256 root = w.root();
uint256 expectedCommitment = w.getRateCommitmentsInRangeBoundsInclusive(index, index)[0];
if (!_verifyMerkleProof(proof, root, index, expectedCommitment, 20)) {
return false;
}
}
return true;
}
function echidna_total_rate_limit_correct() public view returns (bool) {
uint256 computedTotal = 0;
for (uint256 i = 0; i < activeIdCommitments.length; i++) {
(,,,, uint32 rateLimitMem,,,) = w.memberships(activeIdCommitments[i]);
computedTotal += rateLimitMem;
}
return w.currentTotalRateLimit() == computedTotal;
}
function echidna_max_total_rate_limit_valid() public view returns (bool) {
uint32 maxTotal = w.maxTotalRateLimit();
uint256 currentTotal = w.currentTotalRateLimit();
uint32 maxMembership = w.maxMembershipRateLimit();
return maxTotal >= currentTotal && maxTotal >= maxMembership;
}
function echidna_merkle_inserts_integrity() public view returns (bool) {
uint32 nextFree = w.nextFreeIndex();
if (nextFree == 0) return true;
for (uint32 index = 0; index < nextFree; index++) {
uint256 commitment = w.getRateCommitmentsInRangeBoundsInclusive(index, index)[0];
if (indexToRate[index] != 0) {
uint256 exp = PoseidonT3.hash([indexToId[index], uint256(indexToRate[index])]);
if (commitment != exp) {
return false;
}
}
}
return true;
}
function echidna_merkle_erasures_integrity() public view returns (bool) {
uint32 nextFree = w.nextFreeIndex();
if (nextFree == 0) return true;
for (uint32 index = 0; index < nextFree; index++) {
uint256 commitment = w.getRateCommitmentsInRangeBoundsInclusive(index, index)[0];
if (indexToRate[index] == 0) {
continue; // Erased, skip
}
uint256[20] memory proof = w.getMerkleProof(index);
if (!_verifyMerkleProof(proof, w.root(), index, commitment, 20)) {
return false;
}
}
return true;
}
}

145
test/EchidnaTestRaces.t.sol Normal file
View File

@ -0,0 +1,145 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "../src/LinearPriceCalculator.sol";
import "../src/WakuRlnV2.sol";
import "../src/Membership.sol"; // Added import for MembershipUpgradeable
import "./TestStableToken.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
// Echidna invariants and assertions for WakuRlnV2 multi-user timestamp manipulation races
contract EchidnaTestRaces {
WakuRlnV2 internal w;
TestStableToken internal token;
address internal tokenOwner = address(this);
// Storage for multi-user registrations (to track registered IDs)
uint256[] internal registeredIds;
constructor() {
address tokenImpl = address(new TestStableToken());
bytes memory tokenInitData = abi.encodeCall(TestStableToken.initialize, (1_000_000 * 10 ** 18));
address tokenProxyAddr = address(new ERC1967Proxy(tokenImpl, tokenInitData));
token = TestStableToken(tokenProxyAddr);
LinearPriceCalculator priceCalculator = new LinearPriceCalculator(address(token), 1e18 / 20); // Example
address impl = address(new WakuRlnV2());
bytes memory initData =
abi.encodeCall(WakuRlnV2.initialize, (address(priceCalculator), 160_000, 20, 600, 15_552_000, 2_592_000));
address proxyAddr = address(new ERC1967Proxy(impl, initData));
w = WakuRlnV2(proxyAddr);
}
// Function to register a single membership; Echidna can call this multiple times with time advances between
function registerMembership(uint256 idCommitment, uint32 rateLimit) public {
(, uint256 price) = w.priceCalculator().calculate(rateLimit);
token.mint(address(this), price);
token.approve(address(w), price);
w.register(idCommitment, rateLimit, new uint256[](0));
// Add to list (only if successful; reverts otherwise)
registeredIds.push(idCommitment);
}
// Function to attempt extension on a random registered membership and assert based on current time
function attemptExtensionRace(uint256 index) public {
if (registeredIds.length == 0) return; // Skip if no registrations yet
uint256 focusId = registeredIds[index % registeredIds.length];
// Query current membership info from contract to handle updates (e.g., from extensions)
MembershipUpgradeable.MembershipInfo memory info;
(
info.depositAmount,
info.activeDuration,
info.gracePeriodStartTimestamp,
info.gracePeriodDuration,
info.rateLimit,
info.index,
info.holder,
info.token
) = w.memberships(focusId);
// If membership doesn't exist (e.g., erased), skip
if (info.rateLimit == 0) return;
uint256 graceStart = info.gracePeriodStartTimestamp;
uint256 graceEnd = graceStart + uint256(info.gracePeriodDuration);
bool isInGrace = (block.timestamp >= graceStart && block.timestamp < graceEnd);
bool isExpired = (block.timestamp >= graceEnd);
// Additional assertions: State consistency (pre-operation)
assert(w.isInGracePeriod(focusId) == isInGrace);
assert(w.isExpired(focusId) == isExpired);
uint256[] memory ids = new uint256[](1);
ids[0] = focusId;
bool success = false;
try w.extendMemberships(ids) {
success = true;
} catch { }
// Assertion: Extension should succeed only if in grace period (and sender is holder, but always true here)
assert(success == isInGrace);
}
// Function to attempt erasure on a random registered membership and assert based on current time
function attemptErasureRace(uint256 index, bool fullErase) public {
if (registeredIds.length == 0) return; // Skip if no registrations yet
uint256 focusId = registeredIds[index % registeredIds.length];
// Query current membership info from contract to handle updates
MembershipUpgradeable.MembershipInfo memory info;
(
info.depositAmount,
info.activeDuration,
info.gracePeriodStartTimestamp,
info.gracePeriodDuration,
info.rateLimit,
info.index,
info.holder,
info.token
) = w.memberships(focusId);
// If membership doesn't exist (e.g., already erased), skip
if (info.rateLimit == 0) return;
uint256 graceStart = info.gracePeriodStartTimestamp;
uint256 activeEnd = graceStart; // graceStart is end of active
uint256 graceEnd = graceStart + uint256(info.gracePeriodDuration);
bool isActive = (block.timestamp < activeEnd);
bool isExpired = (block.timestamp >= graceEnd);
// Additional assertions: State consistency (pre-operation)
assert(w.isExpired(focusId) == isExpired);
assert(w.isInGracePeriod(focusId) == !(isExpired || isActive));
uint256[] memory ids = new uint256[](1);
ids[0] = focusId;
bool success = false;
try w.eraseMemberships(ids, fullErase) {
success = true;
} catch { }
// Assertion: Erasure should succeed only if not active (i.e., in grace or expired)
// (and for grace, sender == holder, but always true here)
assert(success == !isActive);
// If successful erasure, remove from local registeredIds to avoid stale entries
if (success) {
// Find and remove focusId from array (swap with last and pop)
for (uint256 i = 0; i < registeredIds.length; i++) {
if (registeredIds[i] == focusId) {
registeredIds[i] = registeredIds[registeredIds.length - 1];
registeredIds.pop();
break;
}
}
}
}
}

View File

@ -3,8 +3,9 @@ pragma solidity >=0.8.19 <0.9.0;
import { BaseScript } from "../script/Base.s.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import { ERC20PermitUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import {
ERC20PermitUpgradeable
} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

View File

@ -64,8 +64,9 @@ contract MockPriceCalculator is IPriceCalculator {
}
contract NonUUPSContract {
// A mock contract that does not support UUPS (no proxiable UUID or _authorizeUpgrade)
}
// A mock contract that does not support UUPS (no proxiable UUID or _authorizeUpgrade)
}
contract WakuRlnV2Test is Test {
WakuRlnV2 internal w;
@ -911,8 +912,7 @@ contract WakuRlnV2Test is Test {
w.register(idCommitment, rateLimit, noIdCommitmentsToErase);
// Destructure the memberships mapping tuple, skipping unused fields
(
, // depositAmount
(, // depositAmount
uint32 activeDuration,
uint256 gracePeriodStart,
uint32 gracePeriodDuration,
@ -989,11 +989,10 @@ contract WakuRlnV2Test is Test {
, // depositAmount
, // activeDuration
uint256 graceStart,
uint32 gracePeriodDuration,
, // rateLimit
uint32 gracePeriodDuration,, // rateLimit
, // index
, // holder
// token
// token
) = w.memberships(100);
vm.warp(graceStart + gracePeriodDuration + 1); // Expire one
@ -1024,12 +1023,11 @@ contract WakuRlnV2Test is Test {
(
, // depositAmount
, // activeDuration
uint256 graceStart,
, // gracePeriodDuration
uint256 graceStart,, // gracePeriodDuration
, // rateLimit
, // index
, // holder
// token
// token
) = w.memberships(idCommitment1);
vm.warp(graceStart);
uint256[] memory toErase = new uint256[](1);
@ -1087,12 +1085,11 @@ contract WakuRlnV2Test is Test {
(
, // depositAmount
, // activeDuration
uint256 gracePeriodStart,
, // gracePeriodDuration
uint256 gracePeriodStart,, // gracePeriodDuration
, // rateLimit
, // index
, // holder
// token
// token
) = wZeroGrace.memberships(idCommitment);
// Warp just after active period
@ -1128,11 +1125,10 @@ contract WakuRlnV2Test is Test {
, // depositAmount
, // activeDuration
uint256 graceStart,
uint32 gracePeriodDuration,
, // rateLimit
uint32 gracePeriodDuration,, // rateLimit
, // index
, // holder
// token
// token
) = w.memberships(idCommitment);
vm.warp(graceStart + gracePeriodDuration + 1); // Expire